isa.hh revision 12668
16821SN/A/*
28166SLisa.Hsu@amd.com * Copyright (c) 2010, 2012-2018 ARM Limited
39991Snilay@cs.wisc.edu * All rights reserved
46821SN/A *
56821SN/A * The license below extends only to copyright in the software and shall
66821SN/A * not be construed as granting a license to any other intellectual
76821SN/A * property including but not limited to intellectual property relating
86821SN/A * to a hardware implementation of the functionality of the software
96821SN/A * licensed hereunder.  You may use the software subject to the license
106821SN/A * terms below provided that you ensure that this notice is replicated
116821SN/A * unmodified and in its entirety in all distributions of the software,
126821SN/A * modified or unmodified, in source code or in binary form.
136821SN/A *
146821SN/A * Copyright (c) 2009 The Regents of The University of Michigan
156821SN/A * All rights reserved.
166821SN/A *
176821SN/A * Redistribution and use in source and binary forms, with or without
186821SN/A * modification, are permitted provided that the following conditions are
196821SN/A * met: redistributions of source code must retain the above copyright
206821SN/A * notice, this list of conditions and the following disclaimer;
216821SN/A * redistributions in binary form must reproduce the above copyright
226821SN/A * notice, this list of conditions and the following disclaimer in the
236821SN/A * documentation and/or other materials provided with the distribution;
246821SN/A * neither the name of the copyright holders nor the names of its
256821SN/A * contributors may be used to endorse or promote products derived from
266821SN/A * this software without specific prior written permission.
276821SN/A *
286821SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296821SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
309991Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
316818SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
326818SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336818SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346818SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
359991Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366818SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376818SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386818SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396818SN/A *
406818SN/A * Authors: Gabe Black
416818SN/A */
426818SN/A
436818SN/A#ifndef __ARCH_ARM_ISA_HH__
449991Snilay@cs.wisc.edu#define __ARCH_ARM_ISA_HH__
459991Snilay@cs.wisc.edu
466818SN/A#include "arch/arm/isa_device.hh"
476818SN/A#include "arch/arm/miscregs.hh"
489991Snilay@cs.wisc.edu#include "arch/arm/registers.hh"
499991Snilay@cs.wisc.edu#include "arch/arm/system.hh"
509991Snilay@cs.wisc.edu#include "arch/arm/tlb.hh"
516818SN/A#include "arch/arm/types.hh"
529991Snilay@cs.wisc.edu#include "arch/generic/traits.hh"
539991Snilay@cs.wisc.edu#include "debug/Checkpoint.hh"
546818SN/A#include "enums/VecRegRenameMode.hh"
559991Snilay@cs.wisc.edu#include "sim/sim_object.hh"
569991Snilay@cs.wisc.edu#include "enums/DecoderFlavour.hh"
576818SN/A
586818SN/Astruct ArmISAParams;
599991Snilay@cs.wisc.edustruct DummyArmISADeviceParams;
609991Snilay@cs.wisc.educlass ThreadContext;
619991Snilay@cs.wisc.educlass Checkpoint;
627443SLisa.Hsu@amd.comclass EventManager;
639991Snilay@cs.wisc.edu
646818SN/Anamespace ArmISA
656818SN/A{
666818SN/A    class ISA : public SimObject
676818SN/A    {
686818SN/A      protected:
699991Snilay@cs.wisc.edu        // Parent system
709991Snilay@cs.wisc.edu        ArmSystem *system;
716818SN/A
726818SN/A        // Micro Architecture
739991Snilay@cs.wisc.edu        const Enums::DecoderFlavour _decoderFlavour;
749991Snilay@cs.wisc.edu        const Enums::VecRegRenameMode _vecRegRenameMode;
759991Snilay@cs.wisc.edu
769991Snilay@cs.wisc.edu        /** Dummy device for to handle non-existing ISA devices */
779991Snilay@cs.wisc.edu        DummyISADevice dummyDevice;
789991Snilay@cs.wisc.edu
799991Snilay@cs.wisc.edu        // PMU belonging to this ISA
809991Snilay@cs.wisc.edu        BaseISADevice *pmu;
818166SLisa.Hsu@amd.com
826818SN/A        // Generic timer interface belonging to this ISA
836818SN/A        std::unique_ptr<BaseISADevice> timer;
846818SN/A
856818SN/A        // Cached copies of system-level properties
866818SN/A        bool highestELIs64;
876818SN/A        bool haveSecurity;
886818SN/A        bool haveLPAE;
899991Snilay@cs.wisc.edu        bool haveVirtualization;
909991Snilay@cs.wisc.edu        bool haveLargeAsid64;
916818SN/A        uint8_t physAddrRange64;
929991Snilay@cs.wisc.edu
936818SN/A        /** MiscReg metadata **/
949991Snilay@cs.wisc.edu        struct MiscRegLUTEntry {
959991Snilay@cs.wisc.edu            uint32_t lower;  // Lower half mapped to this register
966818SN/A            uint32_t upper;  // Upper half mapped to this register
976818SN/A            uint64_t _reset; // value taken on reset (i.e. initialization)
989991Snilay@cs.wisc.edu            uint64_t _res0;  // reserved
999991Snilay@cs.wisc.edu            uint64_t _res1;  // reserved
1009991Snilay@cs.wisc.edu            uint64_t _raz;   // read as zero (fixed at 0)
1019991Snilay@cs.wisc.edu            uint64_t _rao;   // read as one (fixed at 1)
1029991Snilay@cs.wisc.edu          public:
1036818SN/A            MiscRegLUTEntry() :
1046818SN/A              lower(0), upper(0),
1057443SLisa.Hsu@amd.com              _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
1067443SLisa.Hsu@amd.com            uint64_t reset() const { return _reset; }
1079991Snilay@cs.wisc.edu            uint64_t res0()  const { return _res0; }
1089991Snilay@cs.wisc.edu            uint64_t res1()  const { return _res1; }
1099991Snilay@cs.wisc.edu            uint64_t raz()   const { return _raz; }
1109991Snilay@cs.wisc.edu            uint64_t rao()   const { return _rao; }
1119991Snilay@cs.wisc.edu            // raz/rao implies writes ignored
1127443SLisa.Hsu@amd.com            uint64_t wi()    const { return _raz | _rao; }
1136818SN/A        };
1146818SN/A
1156818SN/A        /** Metadata table accessible via the value of the register */
1166818SN/A        static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
1179991Snilay@cs.wisc.edu
1189991Snilay@cs.wisc.edu        class MiscRegLUTEntryInitializer {
1199991Snilay@cs.wisc.edu            struct MiscRegLUTEntry &entry;
1209991Snilay@cs.wisc.edu            std::bitset<NUM_MISCREG_INFOS> &info;
1219991Snilay@cs.wisc.edu            typedef const MiscRegLUTEntryInitializer& chain;
1229991Snilay@cs.wisc.edu          public:
1239991Snilay@cs.wisc.edu            chain mapsTo(uint32_t l, uint32_t u = 0) const {
1249991Snilay@cs.wisc.edu                entry.lower = l;
1259991Snilay@cs.wisc.edu                entry.upper = u;
1269991Snilay@cs.wisc.edu                return *this;
1279991Snilay@cs.wisc.edu            }
1289991Snilay@cs.wisc.edu            chain res0(uint64_t mask) const {
1299991Snilay@cs.wisc.edu                entry._res0 = mask;
1308166SLisa.Hsu@amd.com                return *this;
1316818SN/A            }
1328166SLisa.Hsu@amd.com            chain res1(uint64_t mask) const {
1339991Snilay@cs.wisc.edu                entry._res1 = mask;
1349991Snilay@cs.wisc.edu                return *this;
1356818SN/A            }
1369991Snilay@cs.wisc.edu            chain raz(uint64_t mask) const {
1379991Snilay@cs.wisc.edu                entry._raz  = mask;
1386818SN/A                return *this;
1399991Snilay@cs.wisc.edu            }
1406818SN/A            chain rao(uint64_t mask) const {
1419991Snilay@cs.wisc.edu                entry._rao  = mask;
1429991Snilay@cs.wisc.edu                return *this;
1439991Snilay@cs.wisc.edu            }
1449991Snilay@cs.wisc.edu            chain implemented(bool v = true) const {
1459991Snilay@cs.wisc.edu                info[MISCREG_IMPLEMENTED] = v;
1466818SN/A                return *this;
1476818SN/A            }
1489991Snilay@cs.wisc.edu            chain unimplemented() const {
1499991Snilay@cs.wisc.edu                return implemented(false);
1509991Snilay@cs.wisc.edu            }
1519991Snilay@cs.wisc.edu            chain unverifiable(bool v = true) const {
1529991Snilay@cs.wisc.edu                info[MISCREG_UNVERIFIABLE] = v;
1539991Snilay@cs.wisc.edu                return *this;
1549991Snilay@cs.wisc.edu            }
1559991Snilay@cs.wisc.edu            chain warnNotFail(bool v = true) const {
1566818SN/A                info[MISCREG_WARN_NOT_FAIL] = v;
1579991Snilay@cs.wisc.edu                return *this;
1589991Snilay@cs.wisc.edu            }
1599991Snilay@cs.wisc.edu            chain mutex(bool v = true) const {
1609991Snilay@cs.wisc.edu                info[MISCREG_MUTEX] = v;
1619991Snilay@cs.wisc.edu                return *this;
1629991Snilay@cs.wisc.edu            }
1639991Snilay@cs.wisc.edu            chain banked(bool v = true) const {
1646818SN/A                info[MISCREG_BANKED] = v;
1659991Snilay@cs.wisc.edu                return *this;
1669991Snilay@cs.wisc.edu            }
167            chain bankedChild(bool v = true) const {
168                info[MISCREG_BANKED_CHILD] = v;
169                return *this;
170            }
171            chain userNonSecureRead(bool v = true) const {
172                info[MISCREG_USR_NS_RD] = v;
173                return *this;
174            }
175            chain userNonSecureWrite(bool v = true) const {
176                info[MISCREG_USR_NS_WR] = v;
177                return *this;
178            }
179            chain userSecureRead(bool v = true) const {
180                info[MISCREG_USR_S_RD] = v;
181                return *this;
182            }
183            chain userSecureWrite(bool v = true) const {
184                info[MISCREG_USR_S_WR] = v;
185                return *this;
186            }
187            chain user(bool v = true) const {
188                userNonSecureRead(v);
189                userNonSecureWrite(v);
190                userSecureRead(v);
191                userSecureWrite(v);
192                return *this;
193            }
194            chain privNonSecureRead(bool v = true) const {
195                info[MISCREG_PRI_NS_RD] = v;
196                return *this;
197            }
198            chain privNonSecureWrite(bool v = true) const {
199                info[MISCREG_PRI_NS_WR] = v;
200                return *this;
201            }
202            chain privNonSecure(bool v = true) const {
203                privNonSecureRead(v);
204                privNonSecureWrite(v);
205                return *this;
206            }
207            chain privSecureRead(bool v = true) const {
208                info[MISCREG_PRI_S_RD] = v;
209                return *this;
210            }
211            chain privSecureWrite(bool v = true) const {
212                info[MISCREG_PRI_S_WR] = v;
213                return *this;
214            }
215            chain privSecure(bool v = true) const {
216                privSecureRead(v);
217                privSecureWrite(v);
218                return *this;
219            }
220            chain priv(bool v = true) const {
221                privSecure(v);
222                privNonSecure(v);
223                return *this;
224            }
225            chain hypRead(bool v = true) const {
226                info[MISCREG_HYP_RD] = v;
227                return *this;
228            }
229            chain hypWrite(bool v = true) const {
230                info[MISCREG_HYP_WR] = v;
231                return *this;
232            }
233            chain hyp(bool v = true) const {
234                hypRead(v);
235                hypWrite(v);
236                return *this;
237            }
238            chain monSecureRead(bool v = true) const {
239                info[MISCREG_MON_NS0_RD] = v;
240                return *this;
241            }
242            chain monSecureWrite(bool v = true) const {
243                info[MISCREG_MON_NS0_WR] = v;
244                return *this;
245            }
246            chain monNonSecureRead(bool v = true) const {
247                info[MISCREG_MON_NS1_RD] = v;
248                return *this;
249            }
250            chain monNonSecureWrite(bool v = true) const {
251                info[MISCREG_MON_NS1_WR] = v;
252                return *this;
253            }
254            chain mon(bool v = true) const {
255                monSecureRead(v);
256                monSecureWrite(v);
257                monNonSecureRead(v);
258                monNonSecureWrite(v);
259                return *this;
260            }
261            chain monSecure(bool v = true) const {
262                monSecureRead(v);
263                monSecureWrite(v);
264                return *this;
265            }
266            chain monNonSecure(bool v = true) const {
267                monNonSecureRead(v);
268                monNonSecureWrite(v);
269                return *this;
270            }
271            chain allPrivileges(bool v = true) const {
272                userNonSecureRead(v);
273                userNonSecureWrite(v);
274                userSecureRead(v);
275                userSecureWrite(v);
276                privNonSecureRead(v);
277                privNonSecureWrite(v);
278                privSecureRead(v);
279                privSecureWrite(v);
280                hypRead(v);
281                hypWrite(v);
282                monSecureRead(v);
283                monSecureWrite(v);
284                monNonSecureRead(v);
285                monNonSecureWrite(v);
286                return *this;
287            }
288            chain nonSecure(bool v = true) const {
289                userNonSecureRead(v);
290                userNonSecureWrite(v);
291                privNonSecureRead(v);
292                privNonSecureWrite(v);
293                hypRead(v);
294                hypWrite(v);
295                monNonSecureRead(v);
296                monNonSecureWrite(v);
297                return *this;
298            }
299            chain secure(bool v = true) const {
300                userSecureRead(v);
301                userSecureWrite(v);
302                privSecureRead(v);
303                privSecureWrite(v);
304                monSecureRead(v);
305                monSecureWrite(v);
306                return *this;
307            }
308            chain reads(bool v) const {
309                userNonSecureRead(v);
310                userSecureRead(v);
311                privNonSecureRead(v);
312                privSecureRead(v);
313                hypRead(v);
314                monSecureRead(v);
315                monNonSecureRead(v);
316                return *this;
317            }
318            chain writes(bool v) const {
319                userNonSecureWrite(v);
320                userSecureWrite(v);
321                privNonSecureWrite(v);
322                privSecureWrite(v);
323                hypWrite(v);
324                monSecureWrite(v);
325                monNonSecureWrite(v);
326                return *this;
327            }
328            chain exceptUserMode() const {
329                user(0);
330                return *this;
331            }
332            MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
333                                       std::bitset<NUM_MISCREG_INFOS> &i)
334              : entry(e),
335                info(i)
336            {
337                // force unimplemented registers to be thusly declared
338                implemented(1);
339            }
340        };
341
342        const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
343            return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
344                                              miscRegInfo[reg]);
345        }
346
347        void initializeMiscRegMetadata();
348
349        MiscReg miscRegs[NumMiscRegs];
350        const IntRegIndex *intRegMap;
351
352        void
353        updateRegMap(CPSR cpsr)
354        {
355            if (cpsr.width == 0) {
356                intRegMap = IntReg64Map;
357            } else {
358                switch (cpsr.mode) {
359                  case MODE_USER:
360                  case MODE_SYSTEM:
361                    intRegMap = IntRegUsrMap;
362                    break;
363                  case MODE_FIQ:
364                    intRegMap = IntRegFiqMap;
365                    break;
366                  case MODE_IRQ:
367                    intRegMap = IntRegIrqMap;
368                    break;
369                  case MODE_SVC:
370                    intRegMap = IntRegSvcMap;
371                    break;
372                  case MODE_MON:
373                    intRegMap = IntRegMonMap;
374                    break;
375                  case MODE_ABORT:
376                    intRegMap = IntRegAbtMap;
377                    break;
378                  case MODE_HYP:
379                    intRegMap = IntRegHypMap;
380                    break;
381                  case MODE_UNDEFINED:
382                    intRegMap = IntRegUndMap;
383                    break;
384                  default:
385                    panic("Unrecognized mode setting in CPSR.\n");
386                }
387            }
388        }
389
390        BaseISADevice &getGenericTimer(ThreadContext *tc);
391
392
393      private:
394        inline void assert32(ThreadContext *tc) {
395            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
396            assert(cpsr.width);
397        }
398
399        inline void assert64(ThreadContext *tc) {
400            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
401            assert(!cpsr.width);
402        }
403
404      public:
405        void clear();
406        void clear64(const ArmISAParams *p);
407
408        MiscReg readMiscRegNoEffect(int misc_reg) const;
409        MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
410        void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
411        void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
412
413        RegId
414        flattenRegId(const RegId& regId) const
415        {
416            switch (regId.classValue()) {
417              case IntRegClass:
418                return RegId(IntRegClass, flattenIntIndex(regId.index()));
419              case FloatRegClass:
420                return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
421              case VecRegClass:
422                return RegId(VecRegClass, flattenVecIndex(regId.index()));
423              case VecElemClass:
424                return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
425              case CCRegClass:
426                return RegId(CCRegClass, flattenCCIndex(regId.index()));
427              case MiscRegClass:
428                return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
429            }
430            return RegId();
431        }
432
433        int
434        flattenIntIndex(int reg) const
435        {
436            assert(reg >= 0);
437            if (reg < NUM_ARCH_INTREGS) {
438                return intRegMap[reg];
439            } else if (reg < NUM_INTREGS) {
440                return reg;
441            } else if (reg == INTREG_SPX) {
442                CPSR cpsr = miscRegs[MISCREG_CPSR];
443                ExceptionLevel el = opModeToEL(
444                    (OperatingMode) (uint8_t) cpsr.mode);
445                if (!cpsr.sp && el != EL0)
446                    return INTREG_SP0;
447                switch (el) {
448                  case EL3:
449                    return INTREG_SP3;
450                  case EL2:
451                    return INTREG_SP2;
452                  case EL1:
453                    return INTREG_SP1;
454                  case EL0:
455                    return INTREG_SP0;
456                  default:
457                    panic("Invalid exception level");
458                    break;
459                }
460            } else {
461                return flattenIntRegModeIndex(reg);
462            }
463        }
464
465        int
466        flattenFloatIndex(int reg) const
467        {
468            assert(reg >= 0);
469            return reg;
470        }
471
472        int
473        flattenVecIndex(int reg) const
474        {
475            assert(reg >= 0);
476            return reg;
477        }
478
479        int
480        flattenVecElemIndex(int reg) const
481        {
482            assert(reg >= 0);
483            return reg;
484        }
485
486        int
487        flattenCCIndex(int reg) const
488        {
489            assert(reg >= 0);
490            return reg;
491        }
492
493        int
494        flattenMiscIndex(int reg) const
495        {
496            assert(reg >= 0);
497            int flat_idx = reg;
498
499            if (reg == MISCREG_SPSR) {
500                CPSR cpsr = miscRegs[MISCREG_CPSR];
501                switch (cpsr.mode) {
502                  case MODE_EL0T:
503                    warn("User mode does not have SPSR\n");
504                    flat_idx = MISCREG_SPSR;
505                    break;
506                  case MODE_EL1T:
507                  case MODE_EL1H:
508                    flat_idx = MISCREG_SPSR_EL1;
509                    break;
510                  case MODE_EL2T:
511                  case MODE_EL2H:
512                    flat_idx = MISCREG_SPSR_EL2;
513                    break;
514                  case MODE_EL3T:
515                  case MODE_EL3H:
516                    flat_idx = MISCREG_SPSR_EL3;
517                    break;
518                  case MODE_USER:
519                    warn("User mode does not have SPSR\n");
520                    flat_idx = MISCREG_SPSR;
521                    break;
522                  case MODE_FIQ:
523                    flat_idx = MISCREG_SPSR_FIQ;
524                    break;
525                  case MODE_IRQ:
526                    flat_idx = MISCREG_SPSR_IRQ;
527                    break;
528                  case MODE_SVC:
529                    flat_idx = MISCREG_SPSR_SVC;
530                    break;
531                  case MODE_MON:
532                    flat_idx = MISCREG_SPSR_MON;
533                    break;
534                  case MODE_ABORT:
535                    flat_idx = MISCREG_SPSR_ABT;
536                    break;
537                  case MODE_HYP:
538                    flat_idx = MISCREG_SPSR_HYP;
539                    break;
540                  case MODE_UNDEFINED:
541                    flat_idx = MISCREG_SPSR_UND;
542                    break;
543                  default:
544                    warn("Trying to access SPSR in an invalid mode: %d\n",
545                         cpsr.mode);
546                    flat_idx = MISCREG_SPSR;
547                    break;
548                }
549            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
550                // Mutually exclusive CP15 register
551                switch (reg) {
552                  case MISCREG_PRRR_MAIR0:
553                  case MISCREG_PRRR_MAIR0_NS:
554                  case MISCREG_PRRR_MAIR0_S:
555                    {
556                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
557                        // If the muxed reg has been flattened, work out the
558                        // offset and apply it to the unmuxed reg
559                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
560                        if (ttbcr.eae)
561                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
562                                                        idxOffset);
563                        else
564                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
565                                                        idxOffset);
566                    }
567                    break;
568                  case MISCREG_NMRR_MAIR1:
569                  case MISCREG_NMRR_MAIR1_NS:
570                  case MISCREG_NMRR_MAIR1_S:
571                    {
572                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
573                        // If the muxed reg has been flattened, work out the
574                        // offset and apply it to the unmuxed reg
575                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
576                        if (ttbcr.eae)
577                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
578                                                        idxOffset);
579                        else
580                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
581                                                        idxOffset);
582                    }
583                    break;
584                  case MISCREG_PMXEVTYPER_PMCCFILTR:
585                    {
586                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
587                        if (pmselr.sel == 31)
588                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
589                        else
590                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
591                    }
592                    break;
593                  default:
594                    panic("Unrecognized misc. register.\n");
595                    break;
596                }
597            } else {
598                if (miscRegInfo[reg][MISCREG_BANKED]) {
599                    bool secureReg = haveSecurity && !highestELIs64 &&
600                                     inSecureState(miscRegs[MISCREG_SCR],
601                                                   miscRegs[MISCREG_CPSR]);
602                    flat_idx += secureReg ? 2 : 1;
603                }
604            }
605            return flat_idx;
606        }
607
608        std::pair<int,int> getMiscIndices(int misc_reg) const
609        {
610            // Note: indexes of AArch64 registers are left unchanged
611            int flat_idx = flattenMiscIndex(misc_reg);
612
613            if (lookUpMiscReg[flat_idx].lower == 0) {
614                return std::make_pair(flat_idx, 0);
615            }
616
617            // do additional S/NS flattenings if mapped to NS while in S
618            bool S = haveSecurity && !highestELIs64 &&
619                     inSecureState(miscRegs[MISCREG_SCR],
620                                   miscRegs[MISCREG_CPSR]);
621            int lower = lookUpMiscReg[flat_idx].lower;
622            int upper = lookUpMiscReg[flat_idx].upper;
623            // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
624            lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
625            upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
626            return std::make_pair(lower, upper);
627        }
628
629        void serialize(CheckpointOut &cp) const
630        {
631            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
632            SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
633
634            SERIALIZE_SCALAR(highestELIs64);
635            SERIALIZE_SCALAR(haveSecurity);
636            SERIALIZE_SCALAR(haveLPAE);
637            SERIALIZE_SCALAR(haveVirtualization);
638            SERIALIZE_SCALAR(haveLargeAsid64);
639            SERIALIZE_SCALAR(physAddrRange64);
640        }
641        void unserialize(CheckpointIn &cp)
642        {
643            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
644            UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
645            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
646            updateRegMap(tmp_cpsr);
647
648            UNSERIALIZE_SCALAR(highestELIs64);
649            UNSERIALIZE_SCALAR(haveSecurity);
650            UNSERIALIZE_SCALAR(haveLPAE);
651            UNSERIALIZE_SCALAR(haveVirtualization);
652            UNSERIALIZE_SCALAR(haveLargeAsid64);
653            UNSERIALIZE_SCALAR(physAddrRange64);
654        }
655
656        void startup(ThreadContext *tc) {}
657
658        Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
659
660        Enums::VecRegRenameMode
661        vecRegRenameMode() const
662        {
663            return _vecRegRenameMode;
664        }
665
666        /// Explicitly import the otherwise hidden startup
667        using SimObject::startup;
668
669        typedef ArmISAParams Params;
670
671        const Params *params() const;
672
673        ISA(Params *p);
674    };
675}
676
677template<>
678struct initRenameMode<ArmISA::ISA>
679{
680    static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
681    {
682        return isa->vecRegRenameMode();
683    }
684    static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
685    {
686        return mode(isa1) == mode(isa2);
687    }
688};
689
690#endif
691