utility.cc revision 10103:af1ec649e251
1/*
2 * Copyright (c) 2009-2013 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
38 */
39
40
41#include "arch/arm/faults.hh"
42#include "arch/arm/isa_traits.hh"
43#include "arch/arm/system.hh"
44#include "arch/arm/tlb.hh"
45#include "arch/arm/utility.hh"
46#include "arch/arm/vtophys.hh"
47#include "cpu/checker/cpu.hh"
48#include "cpu/base.hh"
49#include "cpu/thread_context.hh"
50#include "mem/fs_translating_port_proxy.hh"
51#include "sim/full_system.hh"
52
53namespace ArmISA {
54
55void
56initCPU(ThreadContext *tc, int cpuId)
57{
58    // Reset CP15?? What does that mean -- ali
59
60    // FPEXC.EN = 0
61
62    static Fault reset = new Reset;
63    reset->invoke(tc);
64}
65
66uint64_t
67getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
68{
69    if (!FullSystem) {
70        panic("getArgument() only implemented for full system mode.\n");
71        M5_DUMMY_RETURN
72    }
73
74    if (fp)
75        panic("getArgument(): Floating point arguments not implemented\n");
76
77    if (inAArch64(tc)) {
78        if (size == (uint16_t)(-1))
79            size = sizeof(uint64_t);
80
81        if (number < 8 /*NumArgumentRegs64*/) {
82               return tc->readIntReg(number);
83        } else {
84            panic("getArgument(): No support reading stack args for AArch64\n");
85        }
86    } else {
87        if (size == (uint16_t)(-1))
88            size = ArmISA::MachineBytes;
89
90        if (number < NumArgumentRegs) {
91            // If the argument is 64 bits, it must be in an even regiser
92            // number. Increment the number here if it isn't even.
93            if (size == sizeof(uint64_t)) {
94                if ((number % 2) != 0)
95                    number++;
96                // Read the two halves of the data. Number is inc here to
97                // get the second half of the 64 bit reg.
98                uint64_t tmp;
99                tmp = tc->readIntReg(number++);
100                tmp |= tc->readIntReg(number) << 32;
101                return tmp;
102            } else {
103               return tc->readIntReg(number);
104            }
105        } else {
106            Addr sp = tc->readIntReg(StackPointerReg);
107            FSTranslatingPortProxy &vp = tc->getVirtProxy();
108            uint64_t arg;
109            if (size == sizeof(uint64_t)) {
110                // If the argument is even it must be aligned
111                if ((number % 2) != 0)
112                    number++;
113                arg = vp.read<uint64_t>(sp +
114                        (number-NumArgumentRegs) * sizeof(uint32_t));
115                // since two 32 bit args == 1 64 bit arg, increment number
116                number++;
117            } else {
118                arg = vp.read<uint32_t>(sp +
119                               (number-NumArgumentRegs) * sizeof(uint32_t));
120            }
121            return arg;
122        }
123    }
124    panic("getArgument() should always return\n");
125}
126
127void
128skipFunction(ThreadContext *tc)
129{
130    PCState newPC = tc->pcState();
131    if (inAArch64(tc)) {
132        newPC.set(tc->readIntReg(INTREG_X30));
133    } else {
134        newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
135    }
136
137    CheckerCPU *checker = tc->getCheckerCpuPtr();
138    if (checker) {
139        tc->pcStateNoRecord(newPC);
140    } else {
141        tc->pcState(newPC);
142    }
143}
144
145void
146copyRegs(ThreadContext *src, ThreadContext *dest)
147{
148    for (int i = 0; i < NumIntRegs; i++)
149        dest->setIntRegFlat(i, src->readIntRegFlat(i));
150
151    for (int i = 0; i < NumFloatRegs; i++)
152        dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
153
154    // Would need to add condition-code regs if implemented
155    assert(NumCCRegs == 0);
156
157    for (int i = 0; i < NumMiscRegs; i++)
158        dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
159
160    // setMiscReg "with effect" will set the misc register mapping correctly.
161    // e.g. updateRegMap(val)
162    dest->setMiscReg(MISCREG_CPSR, src->readMiscRegNoEffect(MISCREG_CPSR));
163
164    // Copy over the PC State
165    dest->pcState(src->pcState());
166
167    // Invalidate the tlb misc register cache
168    dest->getITBPtr()->invalidateMiscReg();
169    dest->getDTBPtr()->invalidateMiscReg();
170}
171
172bool
173inSecureState(ThreadContext *tc)
174{
175    SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
176        tc->readMiscReg(MISCREG_SCR);
177    return ArmSystem::haveSecurity(tc) && inSecureState(
178        scr, tc->readMiscReg(MISCREG_CPSR));
179}
180
181bool
182inAArch64(ThreadContext *tc)
183{
184    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
185    return opModeIs64((OperatingMode) (uint8_t) cpsr.mode);
186}
187
188bool
189longDescFormatInUse(ThreadContext *tc)
190{
191    TTBCR ttbcr = tc->readMiscReg(MISCREG_TTBCR);
192    return ArmSystem::haveLPAE(tc) && ttbcr.eae;
193}
194
195uint32_t
196getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
197{
198    if (arm_sys->multiProc) {
199       return 0x80000000 | // multiprocessor extensions available
200              tc->cpuId();
201    } else {
202       return 0x80000000 |  // multiprocessor extensions available
203              0x40000000 |  // in up system
204              tc->cpuId();
205    }
206}
207
208bool
209ELIs64(ThreadContext *tc, ExceptionLevel el)
210{
211    if (ArmSystem::highestEL(tc) == el)
212        // Register width is hard-wired
213        return ArmSystem::highestELIs64(tc);
214
215    switch (el) {
216      case EL0:
217        return opModeIs64(currOpMode(tc));
218      case EL1:
219        {
220            // @todo: uncomment this to enable Virtualization
221            // if (ArmSystem::haveVirtualization(tc)) {
222            //     HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
223            //     return hcr.rw;
224            // }
225            assert(ArmSystem::haveSecurity(tc));
226            SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
227            return scr.rw;
228        }
229      case EL2:
230        {
231            assert(ArmSystem::haveSecurity(tc));
232            SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
233            return scr.rw;
234        }
235      default:
236        panic("Invalid exception level");
237        break;
238    }
239}
240
241bool
242isBigEndian64(ThreadContext *tc)
243{
244    switch (opModeToEL(currOpMode(tc))) {
245      case EL3:
246        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).ee;
247      case EL2:
248        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).ee;
249      case EL1:
250        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).ee;
251      case EL0:
252        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).e0e;
253      default:
254        panic("Invalid exception level");
255        break;
256    }
257}
258
259Addr
260purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el)
261{
262    TTBCR tcr;
263
264    switch (el) {
265      case EL0:
266      case EL1:
267        tcr = tc->readMiscReg(MISCREG_TCR_EL1);
268        if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
269            return addr | mask(63, 55);
270        else if (!bits(addr, 55, 48) && tcr.tbi0)
271            return bits(addr,55, 0);
272        break;
273      // @todo: uncomment this to enable Virtualization
274      // case EL2:
275      //   assert(ArmSystem::haveVirtualization());
276      //   tcr = tc->readMiscReg(MISCREG_TCR_EL2);
277      //   if (tcr.tbi)
278      //       return addr & mask(56);
279      //   break;
280      case EL3:
281        assert(ArmSystem::haveSecurity(tc));
282        tcr = tc->readMiscReg(MISCREG_TCR_EL3);
283        if (tcr.tbi)
284            return addr & mask(56);
285        break;
286      default:
287        panic("Invalid exception level");
288        break;
289    }
290
291    return addr;  // Nothing to do if this is not a tagged address
292}
293
294Addr
295truncPage(Addr addr)
296{
297    return addr & ~(PageBytes - 1);
298}
299
300Addr
301roundPage(Addr addr)
302{
303    return (addr + PageBytes - 1) & ~(PageBytes - 1);
304}
305
306bool
307mcrMrc15TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
308                  HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
309{
310    bool        isRead;
311    uint32_t    crm;
312    IntRegIndex rt;
313    uint32_t    crn;
314    uint32_t    opc1;
315    uint32_t    opc2;
316    bool        trapToHype = false;
317
318
319    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
320        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
321        trapToHype  = ((uint32_t) hstr) & (1 << crn);
322        trapToHype |= hdcr.tpm  && (crn == 9) && (crm >= 12);
323        trapToHype |= hcr.tidcp && (
324            ((crn ==  9) && ((crm <= 2) || ((crm >= 5) && (crm <= 8)))) ||
325            ((crn == 10) && ((crm <= 1) ||  (crm == 4) || (crm == 8)))  ||
326            ((crn == 11) && ((crm <= 8) ||  (crm == 15)))               );
327
328        if (!trapToHype) {
329            switch (unflattenMiscReg(miscReg)) {
330              case MISCREG_CPACR:
331                trapToHype = hcptr.tcpac;
332                break;
333              case MISCREG_REVIDR:
334              case MISCREG_TCMTR:
335              case MISCREG_TLBTR:
336              case MISCREG_AIDR:
337                trapToHype = hcr.tid1;
338                break;
339              case MISCREG_CTR:
340              case MISCREG_CCSIDR:
341              case MISCREG_CLIDR:
342              case MISCREG_CSSELR:
343                trapToHype = hcr.tid2;
344                break;
345              case MISCREG_ID_PFR0:
346              case MISCREG_ID_PFR1:
347              case MISCREG_ID_DFR0:
348              case MISCREG_ID_AFR0:
349              case MISCREG_ID_MMFR0:
350              case MISCREG_ID_MMFR1:
351              case MISCREG_ID_MMFR2:
352              case MISCREG_ID_MMFR3:
353              case MISCREG_ID_ISAR0:
354              case MISCREG_ID_ISAR1:
355              case MISCREG_ID_ISAR2:
356              case MISCREG_ID_ISAR3:
357              case MISCREG_ID_ISAR4:
358              case MISCREG_ID_ISAR5:
359                trapToHype = hcr.tid3;
360                break;
361              case MISCREG_DCISW:
362              case MISCREG_DCCSW:
363              case MISCREG_DCCISW:
364                trapToHype = hcr.tsw;
365                break;
366              case MISCREG_DCIMVAC:
367              case MISCREG_DCCIMVAC:
368              case MISCREG_DCCMVAC:
369                trapToHype = hcr.tpc;
370                break;
371              case MISCREG_ICIMVAU:
372              case MISCREG_ICIALLU:
373              case MISCREG_ICIALLUIS:
374              case MISCREG_DCCMVAU:
375                trapToHype = hcr.tpu;
376                break;
377              case MISCREG_TLBIALLIS:
378              case MISCREG_TLBIMVAIS:
379              case MISCREG_TLBIASIDIS:
380              case MISCREG_TLBIMVAAIS:
381              case MISCREG_DTLBIALL:
382              case MISCREG_ITLBIALL:
383              case MISCREG_DTLBIMVA:
384              case MISCREG_ITLBIMVA:
385              case MISCREG_DTLBIASID:
386              case MISCREG_ITLBIASID:
387              case MISCREG_TLBIMVAA:
388              case MISCREG_TLBIALL:
389              case MISCREG_TLBIMVA:
390              case MISCREG_TLBIASID:
391                trapToHype = hcr.ttlb;
392                break;
393              case MISCREG_ACTLR:
394                trapToHype = hcr.tac;
395                break;
396              case MISCREG_SCTLR:
397              case MISCREG_TTBR0:
398              case MISCREG_TTBR1:
399              case MISCREG_TTBCR:
400              case MISCREG_DACR:
401              case MISCREG_DFSR:
402              case MISCREG_IFSR:
403              case MISCREG_DFAR:
404              case MISCREG_IFAR:
405              case MISCREG_ADFSR:
406              case MISCREG_AIFSR:
407              case MISCREG_PRRR:
408              case MISCREG_NMRR:
409              case MISCREG_MAIR0:
410              case MISCREG_MAIR1:
411              case MISCREG_CONTEXTIDR:
412                trapToHype = hcr.tvm & !isRead;
413                break;
414              case MISCREG_PMCR:
415                trapToHype = hdcr.tpmcr;
416                break;
417              // No default action needed
418              default:
419                break;
420            }
421        }
422    }
423    return trapToHype;
424}
425
426
427bool
428mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
429                  HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
430{
431    bool        isRead;
432    uint32_t    crm;
433    IntRegIndex rt;
434    uint32_t    crn;
435    uint32_t    opc1;
436    uint32_t    opc2;
437    bool        trapToHype = false;
438
439    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
440        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
441        inform("trap check M:%x N:%x 1:%x 2:%x hdcr %x, hcptr %x, hstr %x\n",
442                crm, crn, opc1, opc2, hdcr, hcptr, hstr);
443        trapToHype  = hdcr.tda  && (opc1 == 0);
444        trapToHype |= hcptr.tta && (opc1 == 1);
445        if (!trapToHype) {
446            switch (unflattenMiscReg(miscReg)) {
447              case MISCREG_DBGOSLSR:
448              case MISCREG_DBGOSLAR:
449              case MISCREG_DBGOSDLR:
450              case MISCREG_DBGPRCR:
451                trapToHype = hdcr.tdosa;
452                break;
453              case MISCREG_DBGDRAR:
454              case MISCREG_DBGDSAR:
455                trapToHype = hdcr.tdra;
456                break;
457              case MISCREG_JIDR:
458                trapToHype = hcr.tid0;
459                break;
460              case MISCREG_JOSCR:
461              case MISCREG_JMCR:
462                trapToHype = hstr.tjdbx;
463                break;
464              case MISCREG_TEECR:
465              case MISCREG_TEEHBR:
466                trapToHype = hstr.ttee;
467                break;
468              // No default action needed
469              default:
470                break;
471            }
472        }
473    }
474    return trapToHype;
475}
476
477bool
478mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
479                    HCR hcr, uint32_t iss)
480{
481    uint32_t    crm;
482    IntRegIndex rt;
483    uint32_t    crn;
484    uint32_t    opc1;
485    uint32_t    opc2;
486    bool        isRead;
487    bool        trapToHype = false;
488
489    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
490        // This is technically the wrong function, but we can re-use it for
491        // the moment because we only need one field, which overlaps with the
492        // mcrmrc layout
493        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
494        trapToHype = ((uint32_t) hstr) & (1 << crm);
495
496        if (!trapToHype) {
497            switch (unflattenMiscReg(miscReg)) {
498              case MISCREG_SCTLR:
499              case MISCREG_TTBR0:
500              case MISCREG_TTBR1:
501              case MISCREG_TTBCR:
502              case MISCREG_DACR:
503              case MISCREG_DFSR:
504              case MISCREG_IFSR:
505              case MISCREG_DFAR:
506              case MISCREG_IFAR:
507              case MISCREG_ADFSR:
508              case MISCREG_AIFSR:
509              case MISCREG_PRRR:
510              case MISCREG_NMRR:
511              case MISCREG_MAIR0:
512              case MISCREG_MAIR1:
513              case MISCREG_CONTEXTIDR:
514                trapToHype = hcr.tvm & !isRead;
515                break;
516              // No default action needed
517              default:
518                break;
519            }
520        }
521    }
522    return trapToHype;
523}
524
525bool
526msrMrs64TrapToSup(const MiscRegIndex miscReg, ExceptionLevel el,
527                  CPACR cpacr /* CPACR_EL1 */)
528{
529    bool trapToSup = false;
530    switch (miscReg) {
531      case MISCREG_FPCR:
532      case MISCREG_FPSR:
533      case MISCREG_FPEXC32_EL2:
534        if ((el == EL0 && cpacr.fpen != 0x3) ||
535            (el == EL1 && !(cpacr.fpen & 0x1)))
536            trapToSup = true;
537        break;
538      default:
539        break;
540    }
541    return trapToSup;
542}
543
544bool
545msrMrs64TrapToHyp(const MiscRegIndex miscReg, bool isRead,
546                  CPTR cptr /* CPTR_EL2 */,
547                  HCR hcr /* HCR_EL2 */,
548                  bool * isVfpNeon)
549{
550    bool trapToHyp = false;
551    *isVfpNeon = false;
552
553    switch (miscReg) {
554      // FP/SIMD regs
555      case MISCREG_FPCR:
556      case MISCREG_FPSR:
557      case MISCREG_FPEXC32_EL2:
558        trapToHyp = cptr.tfp;
559        *isVfpNeon = true;
560        break;
561      // CPACR
562      case MISCREG_CPACR_EL1:
563        trapToHyp = cptr.tcpac;
564        break;
565      // Virtual memory control regs
566      case MISCREG_SCTLR_EL1:
567      case MISCREG_TTBR0_EL1:
568      case MISCREG_TTBR1_EL1:
569      case MISCREG_TCR_EL1:
570      case MISCREG_ESR_EL1:
571      case MISCREG_FAR_EL1:
572      case MISCREG_AFSR0_EL1:
573      case MISCREG_AFSR1_EL1:
574      case MISCREG_MAIR_EL1:
575      case MISCREG_AMAIR_EL1:
576      case MISCREG_CONTEXTIDR_EL1:
577        trapToHyp = (hcr.trvm && isRead) || (hcr.tvm && !isRead);
578        break;
579      // TLB maintenance instructions
580      case MISCREG_TLBI_VMALLE1:
581      case MISCREG_TLBI_VAE1_Xt:
582      case MISCREG_TLBI_ASIDE1_Xt:
583      case MISCREG_TLBI_VAAE1_Xt:
584      case MISCREG_TLBI_VALE1_Xt:
585      case MISCREG_TLBI_VAALE1_Xt:
586      case MISCREG_TLBI_VMALLE1IS:
587      case MISCREG_TLBI_VAE1IS_Xt:
588      case MISCREG_TLBI_ASIDE1IS_Xt:
589      case MISCREG_TLBI_VAAE1IS_Xt:
590      case MISCREG_TLBI_VALE1IS_Xt:
591      case MISCREG_TLBI_VAALE1IS_Xt:
592        trapToHyp = hcr.ttlb;
593        break;
594      // Cache maintenance instructions to the point of unification
595      case MISCREG_IC_IVAU_Xt:
596      case MISCREG_ICIALLU:
597      case MISCREG_ICIALLUIS:
598      case MISCREG_DC_CVAU_Xt:
599        trapToHyp = hcr.tpu;
600        break;
601      // Data/Unified cache maintenance instructions to the point of coherency
602      case MISCREG_DC_IVAC_Xt:
603      case MISCREG_DC_CIVAC_Xt:
604      case MISCREG_DC_CVAC_Xt:
605        trapToHyp = hcr.tpc;
606        break;
607      // Data/Unified cache maintenance instructions by set/way
608      case MISCREG_DC_ISW_Xt:
609      case MISCREG_DC_CSW_Xt:
610      case MISCREG_DC_CISW_Xt:
611        trapToHyp = hcr.tsw;
612        break;
613      // ACTLR
614      case MISCREG_ACTLR_EL1:
615        trapToHyp = hcr.tacr;
616        break;
617
618      // @todo: Trap implementation-dependent functionality based on
619      // hcr.tidcp
620
621      // ID regs, group 3
622      case MISCREG_ID_PFR0_EL1:
623      case MISCREG_ID_PFR1_EL1:
624      case MISCREG_ID_DFR0_EL1:
625      case MISCREG_ID_AFR0_EL1:
626      case MISCREG_ID_MMFR0_EL1:
627      case MISCREG_ID_MMFR1_EL1:
628      case MISCREG_ID_MMFR2_EL1:
629      case MISCREG_ID_MMFR3_EL1:
630      case MISCREG_ID_ISAR0_EL1:
631      case MISCREG_ID_ISAR1_EL1:
632      case MISCREG_ID_ISAR2_EL1:
633      case MISCREG_ID_ISAR3_EL1:
634      case MISCREG_ID_ISAR4_EL1:
635      case MISCREG_ID_ISAR5_EL1:
636      case MISCREG_MVFR0_EL1:
637      case MISCREG_MVFR1_EL1:
638      case MISCREG_MVFR2_EL1:
639      case MISCREG_ID_AA64PFR0_EL1:
640      case MISCREG_ID_AA64PFR1_EL1:
641      case MISCREG_ID_AA64DFR0_EL1:
642      case MISCREG_ID_AA64DFR1_EL1:
643      case MISCREG_ID_AA64ISAR0_EL1:
644      case MISCREG_ID_AA64ISAR1_EL1:
645      case MISCREG_ID_AA64MMFR0_EL1:
646      case MISCREG_ID_AA64MMFR1_EL1:
647      case MISCREG_ID_AA64AFR0_EL1:
648      case MISCREG_ID_AA64AFR1_EL1:
649        assert(isRead);
650        trapToHyp = hcr.tid3;
651        break;
652      // ID regs, group 2
653      case MISCREG_CTR_EL0:
654      case MISCREG_CCSIDR_EL1:
655      case MISCREG_CLIDR_EL1:
656      case MISCREG_CSSELR_EL1:
657        trapToHyp = hcr.tid2;
658        break;
659      // ID regs, group 1
660      case MISCREG_AIDR_EL1:
661      case MISCREG_REVIDR_EL1:
662        assert(isRead);
663        trapToHyp = hcr.tid1;
664        break;
665      default:
666        break;
667    }
668    return trapToHyp;
669}
670
671bool
672msrMrs64TrapToMon(const MiscRegIndex miscReg, CPTR cptr /* CPTR_EL3 */,
673                  ExceptionLevel el, bool * isVfpNeon)
674{
675    bool trapToMon = false;
676    *isVfpNeon = false;
677
678    switch (miscReg) {
679      // FP/SIMD regs
680      case MISCREG_FPCR:
681      case MISCREG_FPSR:
682      case MISCREG_FPEXC32_EL2:
683        trapToMon = cptr.tfp;
684        *isVfpNeon = true;
685        break;
686      // CPACR, CPTR
687      case MISCREG_CPACR_EL1:
688        if (el == EL1) {
689           trapToMon = cptr.tcpac;
690        }
691        break;
692      case MISCREG_CPTR_EL2:
693        if (el == EL2) {
694            trapToMon = cptr.tcpac;
695        }
696        break;
697      default:
698        break;
699    }
700    return trapToMon;
701}
702
703bool
704decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int &regIdx,
705                      CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
706{
707    OperatingMode mode = MODE_UNDEFINED;
708    bool          ok = true;
709
710    // R mostly indicates if its a int register or a misc reg, we override
711    // below if the few corner cases
712    isIntReg = !r;
713    // Loosely based on ARM ARM issue C section B9.3.10
714    if (r) {
715        switch (sysM)
716        {
717          case 0xE:
718            regIdx = MISCREG_SPSR_FIQ;
719            mode   = MODE_FIQ;
720            break;
721          case 0x10:
722            regIdx = MISCREG_SPSR_IRQ;
723            mode   = MODE_IRQ;
724            break;
725          case 0x12:
726            regIdx = MISCREG_SPSR_SVC;
727            mode   = MODE_SVC;
728            break;
729          case 0x14:
730            regIdx = MISCREG_SPSR_ABT;
731            mode   = MODE_ABORT;
732            break;
733          case 0x16:
734            regIdx = MISCREG_SPSR_UND;
735            mode   = MODE_UNDEFINED;
736            break;
737          case 0x1C:
738            regIdx = MISCREG_SPSR_MON;
739            mode   = MODE_MON;
740            break;
741          case 0x1E:
742            regIdx = MISCREG_SPSR_HYP;
743            mode   = MODE_HYP;
744            break;
745          default:
746            ok = false;
747            break;
748        }
749    } else {
750        int sysM4To3 = bits(sysM, 4, 3);
751
752        if (sysM4To3 == 0) {
753            mode = MODE_USER;
754            regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
755        } else if (sysM4To3 == 1) {
756            mode = MODE_FIQ;
757            regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
758        } else if (sysM4To3 == 3) {
759            if (bits(sysM, 1) == 0) {
760                mode = MODE_MON;
761                regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
762            } else {
763                mode = MODE_HYP;
764                if (bits(sysM, 0) == 1) {
765                    regIdx = intRegInMode(mode, 13); // R13 in HYP
766                } else {
767                    isIntReg = false;
768                    regIdx   = MISCREG_ELR_HYP;
769                }
770            }
771        } else { // Other Banked registers
772            int sysM2 = bits(sysM, 2);
773            int sysM1 = bits(sysM, 1);
774
775            mode  = (OperatingMode) ( ((sysM2 ||  sysM1) << 0) |
776                                      (1                 << 1) |
777                                      ((sysM2 && !sysM1) << 2) |
778                                      ((sysM2 &&  sysM1) << 3) |
779                                      (1                 << 4) );
780            regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
781            // Don't flatten the register here. This is going to go through
782            // setIntReg() which will do the flattening
783            ok &= mode != cpsr.mode;
784        }
785    }
786
787    // Check that the requested register is accessable from the current mode
788    if (ok && checkSecurity && mode != cpsr.mode) {
789        switch (cpsr.mode)
790        {
791          case MODE_USER:
792            ok = false;
793            break;
794          case MODE_FIQ:
795            ok &=  mode != MODE_HYP;
796            ok &= (mode != MODE_MON) || !scr.ns;
797            break;
798          case MODE_HYP:
799            ok &=  mode != MODE_MON;
800            ok &= (mode != MODE_FIQ) || !nsacr.rfr;
801            break;
802          case MODE_IRQ:
803          case MODE_SVC:
804          case MODE_ABORT:
805          case MODE_UNDEFINED:
806          case MODE_SYSTEM:
807            ok &=  mode != MODE_HYP;
808            ok &= (mode != MODE_MON) || !scr.ns;
809            ok &= (mode != MODE_FIQ) || !nsacr.rfr;
810            break;
811          // can access everything, no further checks required
812          case MODE_MON:
813            break;
814          default:
815            panic("unknown Mode 0x%x\n", cpsr.mode);
816            break;
817        }
818    }
819    return (ok);
820}
821
822bool
823vfpNeonEnabled(uint32_t &seq, HCPTR hcptr, NSACR nsacr, CPACR cpacr, CPSR cpsr,
824               uint32_t &iss, bool &trap, ThreadContext *tc, FPEXC fpexc,
825               bool isSIMD)
826{
827    iss                     = 0;
828    trap                    = false;
829    bool undefined          = false;
830    bool haveSecurity       = ArmSystem::haveSecurity(tc);
831    bool haveVirtualization = ArmSystem::haveVirtualization(tc);
832    bool isSecure           = inSecureState(tc);
833
834    // Non-secure view of CPACR and HCPTR determines behavior
835    // Copy register values
836    uint8_t cpacr_cp10   = cpacr.cp10;
837    bool    cpacr_asedis = cpacr.asedis;
838    bool    hcptr_cp10   = false;
839    bool    hcptr_tase   = false;
840
841    bool cp10_enabled = cpacr.cp10 == 0x3
842                      || (cpacr.cp10 == 0x1 && inPrivilegedMode(cpsr));
843
844    bool cp11_enabled =  cpacr.cp11 == 0x3
845                      || (cpacr.cp11 == 0x1 && inPrivilegedMode(cpsr));
846
847    if (cp11_enabled) {
848        undefined |= !(fpexc.en && cp10_enabled);
849    } else {
850        undefined |= !(fpexc.en && cp10_enabled && (cpacr.cp11 == cpacr.cp10));
851    }
852
853    if (haveVirtualization) {
854        hcptr_cp10 = hcptr.tcp10;
855        undefined |= hcptr.tcp10 != hcptr.tcp11;
856        hcptr_tase = hcptr.tase;
857    }
858
859    if (haveSecurity) {
860        undefined |= nsacr.cp10 != nsacr.cp11;
861        if (!isSecure) {
862            // Modify register values to the Non-secure view
863            if (!nsacr.cp10) {
864                cpacr_cp10 = 0;
865                if (haveVirtualization) {
866                    hcptr_cp10 = true;
867                }
868            }
869            if (nsacr.nsasedis) {
870                cpacr_asedis = true;
871                if (haveVirtualization) {
872                    hcptr_tase = true;
873                }
874            }
875        }
876    }
877
878    // Check Coprocessor Access Control Register for permission to use CP10/11.
879    if (!haveVirtualization || (cpsr.mode != MODE_HYP)) {
880        switch (cpacr_cp10)
881        {
882            case 0:
883                undefined = true;
884                break;
885            case 1:
886                undefined |= inUserMode(cpsr);
887                break;
888        }
889
890        // Check if SIMD operations are disabled
891        if (isSIMD && cpacr_asedis) undefined = true;
892    }
893
894    // If required, check FPEXC enabled bit.
895    undefined |= !fpexc.en;
896
897    if (haveSecurity && haveVirtualization && !isSecure) {
898        if (hcptr_cp10 || (isSIMD && hcptr_tase)) {
899            iss  = isSIMD ? (1 << 5) : 0xA;
900            trap = true;
901        }
902    }
903
904    return (!undefined);
905}
906
907bool
908SPAlignmentCheckEnabled(ThreadContext* tc)
909{
910    switch (opModeToEL(currOpMode(tc))) {
911      case EL3:
912        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).sa;
913      case EL2:
914        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).sa;
915      case EL1:
916        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa;
917      case EL0:
918        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa0;
919      default:
920        panic("Invalid exception level");
921        break;
922    }
923}
924
925int
926decodePhysAddrRange64(uint8_t pa_enc)
927{
928    switch (pa_enc) {
929      case 0x0:
930        return 32;
931      case 0x1:
932        return 36;
933      case 0x2:
934        return 40;
935      case 0x3:
936        return 42;
937      case 0x4:
938        return 44;
939      case 0x5:
940      case 0x6:
941      case 0x7:
942        return 48;
943      default:
944        panic("Invalid phys. address range encoding");
945    }
946}
947
948uint8_t
949encodePhysAddrRange64(int pa_size)
950{
951    switch (pa_size) {
952      case 32:
953        return 0x0;
954      case 36:
955        return 0x1;
956      case 40:
957        return 0x2;
958      case 42:
959        return 0x3;
960      case 44:
961        return 0x4;
962      case 48:
963        return 0x5;
964      default:
965        panic("Invalid phys. address range");
966    }
967}
968
969} // namespace ArmISA
970