isa.hh revision 7404:bfc74724914e
1/*
2 * Copyright (c) 2010 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 * Copyright (c) 2009 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Gabe Black
41 */
42
43#ifndef __ARCH_ARM_ISA_HH__
44#define __ARCH_ARM_ISA_HH__
45
46#include "arch/arm/registers.hh"
47#include "arch/arm/tlb.hh"
48#include "arch/arm/types.hh"
49
50class ThreadContext;
51class Checkpoint;
52class EventManager;
53
54namespace ArmISA
55{
56    class ISA
57    {
58      protected:
59        MiscReg miscRegs[NumMiscRegs];
60        const IntRegIndex *intRegMap;
61
62        void
63        updateRegMap(CPSR cpsr)
64        {
65            switch (cpsr.mode) {
66              case MODE_USER:
67              case MODE_SYSTEM:
68                intRegMap = IntRegUsrMap;
69                break;
70              case MODE_FIQ:
71                intRegMap = IntRegFiqMap;
72                break;
73              case MODE_IRQ:
74                intRegMap = IntRegIrqMap;
75                break;
76              case MODE_SVC:
77                intRegMap = IntRegSvcMap;
78                break;
79              case MODE_MON:
80                intRegMap = IntRegMonMap;
81                break;
82              case MODE_ABORT:
83                intRegMap = IntRegAbtMap;
84                break;
85              case MODE_UNDEFINED:
86                intRegMap = IntRegUndMap;
87                break;
88              default:
89                panic("Unrecognized mode setting in CPSR.\n");
90            }
91        }
92
93      public:
94        void clear()
95        {
96            SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST];
97
98            memset(miscRegs, 0, sizeof(miscRegs));
99            CPSR cpsr = 0;
100            cpsr.mode = MODE_USER;
101            miscRegs[MISCREG_CPSR] = cpsr;
102            updateRegMap(cpsr);
103
104            SCTLR sctlr = 0;
105            sctlr.nmfi = (bool)sctlr_rst.nmfi;
106            sctlr.v = (bool)sctlr_rst.v;
107            sctlr.u    = 1;
108            sctlr.rao1 = 1;
109            sctlr.rao2 = 1;
110            sctlr.rao3 = 1;
111            sctlr.rao4 = 1;
112            miscRegs[MISCREG_SCTLR] = sctlr;
113            miscRegs[MISCREG_SCTLR_RST] = sctlr_rst;
114
115
116            /*
117             * Technically this should be 0, but we don't support those
118             * settings.
119             */
120            CPACR cpacr = 0;
121            // Enable CP 10, 11
122            cpacr.cp10 = 0x3;
123            cpacr.cp11 = 0x3;
124            miscRegs[MISCREG_CPACR] = cpacr;
125
126            /* Start with an event in the mailbox */
127            miscRegs[MISCREG_SEV_MAILBOX] = 1;
128
129            /*
130             * Implemented = '5' from "M5",
131             * Variant = 0,
132             */
133            miscRegs[MISCREG_MIDR] =
134                (0x35 << 24) | //Implementor is '5' from "M5"
135                (0 << 20)    | //Variant
136                (0xf << 16)  | //Architecture from CPUID scheme
137                (0 << 4)     | //Primary part number
138                (0 << 0)     | //Revision
139                0;
140
141            // Separate Instruction and Data TLBs.
142            miscRegs[MISCREG_TLBTR] = 1;
143
144            MVFR0 mvfr0 = 0;
145            mvfr0.advSimdRegisters = 2;
146            mvfr0.singlePrecision = 2;
147            mvfr0.doublePrecision = 2;
148            mvfr0.vfpExceptionTrapping = 0;
149            mvfr0.divide = 1;
150            mvfr0.squareRoot = 1;
151            mvfr0.shortVectors = 1;
152            mvfr0.roundingModes = 1;
153            miscRegs[MISCREG_MVFR0] = mvfr0;
154
155            MVFR1 mvfr1 = 0;
156            mvfr1.flushToZero = 1;
157            mvfr1.defaultNaN = 1;
158            mvfr1.advSimdLoadStore = 1;
159            mvfr1.advSimdInteger = 1;
160            mvfr1.advSimdSinglePrecision = 1;
161            mvfr1.advSimdHalfPrecision = 1;
162            mvfr1.vfpHalfPrecision = 1;
163            miscRegs[MISCREG_MVFR1] = mvfr1;
164
165            miscRegs[MISCREG_MPIDR] = 0;
166
167            //XXX We need to initialize the rest of the state.
168        }
169
170        MiscReg
171        readMiscRegNoEffect(int misc_reg)
172        {
173            assert(misc_reg < NumMiscRegs);
174            if (misc_reg == MISCREG_SPSR) {
175                CPSR cpsr = miscRegs[MISCREG_CPSR];
176                switch (cpsr.mode) {
177                  case MODE_USER:
178                    return miscRegs[MISCREG_SPSR];
179                  case MODE_FIQ:
180                    return miscRegs[MISCREG_SPSR_FIQ];
181                  case MODE_IRQ:
182                    return miscRegs[MISCREG_SPSR_IRQ];
183                  case MODE_SVC:
184                    return miscRegs[MISCREG_SPSR_SVC];
185                  case MODE_MON:
186                    return miscRegs[MISCREG_SPSR_MON];
187                  case MODE_ABORT:
188                    return miscRegs[MISCREG_SPSR_ABT];
189                  case MODE_UNDEFINED:
190                    return miscRegs[MISCREG_SPSR_UND];
191                  default:
192                    return miscRegs[MISCREG_SPSR];
193                }
194            }
195            return miscRegs[misc_reg];
196        }
197
198        MiscReg
199        readMiscReg(int misc_reg, ThreadContext *tc)
200        {
201            if (misc_reg == MISCREG_CPSR) {
202                CPSR cpsr = miscRegs[misc_reg];
203                Addr pc = tc->readPC();
204                if (pc & (ULL(1) << PcJBitShift))
205                    cpsr.j = 1;
206                else
207                    cpsr.j = 0;
208                if (pc & (ULL(1) << PcTBitShift))
209                    cpsr.t = 1;
210                else
211                    cpsr.t = 0;
212                return cpsr;
213            }
214            if (misc_reg >= MISCREG_CP15_UNIMP_START &&
215                misc_reg < MISCREG_CP15_END) {
216                panic("Unimplemented CP15 register %s read.\n",
217                      miscRegName[misc_reg]);
218            }
219            switch (misc_reg) {
220              case MISCREG_CLIDR:
221                warn("The clidr register always reports 0 caches.\n");
222                break;
223              case MISCREG_CCSIDR:
224                warn("The ccsidr register isn't implemented and "
225                        "always reads as 0.\n");
226                break;
227              case MISCREG_ID_PFR0:
228                return 0x1031; // ThumbEE | !Jazelle | Thumb | ARM
229            }
230            return readMiscRegNoEffect(misc_reg);
231        }
232
233        void
234        setMiscRegNoEffect(int misc_reg, const MiscReg &val)
235        {
236            assert(misc_reg < NumMiscRegs);
237            if (misc_reg == MISCREG_SPSR) {
238                CPSR cpsr = miscRegs[MISCREG_CPSR];
239                switch (cpsr.mode) {
240                  case MODE_USER:
241                    miscRegs[MISCREG_SPSR] = val;
242                    return;
243                  case MODE_FIQ:
244                    miscRegs[MISCREG_SPSR_FIQ] = val;
245                    return;
246                  case MODE_IRQ:
247                    miscRegs[MISCREG_SPSR_IRQ] = val;
248                    return;
249                  case MODE_SVC:
250                    miscRegs[MISCREG_SPSR_SVC] = val;
251                    return;
252                  case MODE_MON:
253                    miscRegs[MISCREG_SPSR_MON] = val;
254                    return;
255                  case MODE_ABORT:
256                    miscRegs[MISCREG_SPSR_ABT] = val;
257                    return;
258                  case MODE_UNDEFINED:
259                    miscRegs[MISCREG_SPSR_UND] = val;
260                    return;
261                  default:
262                    miscRegs[MISCREG_SPSR] = val;
263                    return;
264                }
265            }
266            miscRegs[misc_reg] = val;
267        }
268
269        void
270        setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
271        {
272            MiscReg newVal = val;
273            if (misc_reg == MISCREG_CPSR) {
274                updateRegMap(val);
275                CPSR cpsr = val;
276                DPRINTF(Arm, "Updating CPSR to %#x f:%d i:%d a:%d mode:%#x\n",
277                        cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode);
278                Addr npc = tc->readNextPC() & ~PcModeMask;
279                if (cpsr.j)
280                    npc = npc | (ULL(1) << PcJBitShift);
281                if (cpsr.t)
282                    npc = npc | (ULL(1) << PcTBitShift);
283
284                tc->setNextPC(npc);
285            }
286            if (misc_reg >= MISCREG_CP15_UNIMP_START &&
287                misc_reg < MISCREG_CP15_END) {
288                panic("Unimplemented CP15 register %s wrote with %#x.\n",
289                      miscRegName[misc_reg], val);
290            }
291            switch (misc_reg) {
292              case MISCREG_CPACR:
293                {
294                    CPACR newCpacr = 0;
295                    CPACR valCpacr = val;
296                    newCpacr.cp10 = valCpacr.cp10;
297                    newCpacr.cp11 = valCpacr.cp11;
298                    if (newCpacr.cp10 != 0x3 || newCpacr.cp11 != 3) {
299                        panic("Disabling coprocessors isn't implemented.\n");
300                    }
301                    newVal = newCpacr;
302                }
303                break;
304              case MISCREG_CSSELR:
305                warn("The csselr register isn't implemented.\n");
306                break;
307              case MISCREG_FPSCR:
308                {
309                    const uint32_t ones = (uint32_t)(-1);
310                    FPSCR fpscrMask = 0;
311                    fpscrMask.ioc = ones;
312                    fpscrMask.dzc = ones;
313                    fpscrMask.ofc = ones;
314                    fpscrMask.ufc = ones;
315                    fpscrMask.ixc = ones;
316                    fpscrMask.idc = ones;
317                    fpscrMask.len = ones;
318                    fpscrMask.stride = ones;
319                    fpscrMask.rMode = ones;
320                    fpscrMask.fz = ones;
321                    fpscrMask.dn = ones;
322                    fpscrMask.ahp = ones;
323                    fpscrMask.qc = ones;
324                    fpscrMask.v = ones;
325                    fpscrMask.c = ones;
326                    fpscrMask.z = ones;
327                    fpscrMask.n = ones;
328                    newVal = (newVal & (uint32_t)fpscrMask) |
329                             (miscRegs[MISCREG_FPSCR] & ~(uint32_t)fpscrMask);
330                }
331                break;
332              case MISCREG_FPEXC:
333                {
334                    const uint32_t fpexcMask = 0x60000000;
335                    newVal = (newVal & fpexcMask) |
336                             (miscRegs[MISCREG_FPEXC] & ~fpexcMask);
337                }
338                break;
339              case MISCREG_SCTLR:
340                {
341                    SCTLR sctlr = miscRegs[MISCREG_SCTLR];
342                    SCTLR new_sctlr = newVal;
343                    new_sctlr.nmfi =  (bool)sctlr.nmfi;
344                    miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr;
345                    return;
346                }
347              case MISCREG_TLBTR:
348              case MISCREG_MVFR0:
349              case MISCREG_MVFR1:
350              case MISCREG_MPIDR:
351              case MISCREG_FPSID:
352                return;
353              case MISCREG_TLBIALLIS:
354              case MISCREG_TLBIALL:
355                warn("Need to flush all TLBs in MP\n");
356                tc->getITBPtr()->flushAll();
357                tc->getDTBPtr()->flushAll();
358                return;
359              case MISCREG_ITLBIALL:
360                tc->getITBPtr()->flushAll();
361                return;
362              case MISCREG_DTLBIALL:
363                tc->getDTBPtr()->flushAll();
364                return;
365              case MISCREG_TLBIMVAIS:
366              case MISCREG_TLBIMVA:
367                warn("Need to flush all TLBs in MP\n");
368                tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
369                        bits(newVal, 7,0));
370                tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
371                        bits(newVal, 7,0));
372                return;
373              case MISCREG_TLBIASIDIS:
374              case MISCREG_TLBIASID:
375                warn("Need to flush all TLBs in MP\n");
376                tc->getITBPtr()->flushAsid(bits(newVal, 7,0));
377                tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
378                return;
379              case MISCREG_TLBIMVAAIS:
380              case MISCREG_TLBIMVAA:
381                warn("Need to flush all TLBs in MP\n");
382                tc->getITBPtr()->flushMva(mbits(newVal, 31,12));
383                tc->getDTBPtr()->flushMva(mbits(newVal, 31,12));
384                return;
385              case MISCREG_ITLBIMVA:
386                tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
387                        bits(newVal, 7,0));
388                return;
389              case MISCREG_DTLBIMVA:
390                tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
391                        bits(newVal, 7,0));
392                return;
393              case MISCREG_ITLBIASID:
394                tc->getITBPtr()->flushAsid(bits(newVal, 7,0));
395                return;
396              case MISCREG_DTLBIASID:
397                tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
398                return;
399            }
400            setMiscRegNoEffect(misc_reg, newVal);
401        }
402
403        int
404        flattenIntIndex(int reg)
405        {
406            assert(reg >= 0);
407            if (reg < NUM_ARCH_INTREGS) {
408                return intRegMap[reg];
409            } else if (reg < NUM_INTREGS) {
410                return reg;
411            } else {
412                int mode = reg / intRegsPerMode;
413                reg = reg % intRegsPerMode;
414                switch (mode) {
415                  case MODE_USER:
416                  case MODE_SYSTEM:
417                    return INTREG_USR(reg);
418                  case MODE_FIQ:
419                    return INTREG_FIQ(reg);
420                  case MODE_IRQ:
421                    return INTREG_IRQ(reg);
422                  case MODE_SVC:
423                    return INTREG_SVC(reg);
424                  case MODE_MON:
425                    return INTREG_MON(reg);
426                  case MODE_ABORT:
427                    return INTREG_ABT(reg);
428                  case MODE_UNDEFINED:
429                    return INTREG_UND(reg);
430                  default:
431                    panic("Flattening into an unknown mode.\n");
432                }
433            }
434        }
435
436        int
437        flattenFloatIndex(int reg)
438        {
439            return reg;
440        }
441
442        void serialize(EventManager *em, std::ostream &os)
443        {}
444        void unserialize(EventManager *em, Checkpoint *cp,
445                const std::string &section)
446        {}
447
448        ISA()
449        {
450            SCTLR sctlr;
451            sctlr = 0;
452            miscRegs[MISCREG_SCTLR_RST] = sctlr;
453
454            clear();
455        }
456    };
457}
458
459#endif
460