isa.hh (13393:659fdbcd5722) isa.hh (13395:0f064dae9f6b)
1/*
2 * Copyright (c) 2010, 2012-2018 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/isa_device.hh"
47#include "arch/arm/miscregs.hh"
48#include "arch/arm/registers.hh"
49#include "arch/arm/system.hh"
50#include "arch/arm/tlb.hh"
51#include "arch/arm/types.hh"
52#include "arch/generic/traits.hh"
53#include "debug/Checkpoint.hh"
54#include "enums/VecRegRenameMode.hh"
55#include "sim/sim_object.hh"
56#include "enums/DecoderFlavour.hh"
57
58struct ArmISAParams;
59struct DummyArmISADeviceParams;
60class ThreadContext;
61class Checkpoint;
62class EventManager;
63
64namespace ArmISA
65{
66 class ISA : public SimObject
67 {
68 protected:
69 // Parent system
70 ArmSystem *system;
71
72 // Micro Architecture
73 const Enums::DecoderFlavour _decoderFlavour;
74 const Enums::VecRegRenameMode _vecRegRenameMode;
75
76 /** Dummy device for to handle non-existing ISA devices */
77 DummyISADevice dummyDevice;
78
79 // PMU belonging to this ISA
80 BaseISADevice *pmu;
81
82 // Generic timer interface belonging to this ISA
83 std::unique_ptr<BaseISADevice> timer;
84
85 // Cached copies of system-level properties
86 bool highestELIs64;
87 bool haveSecurity;
88 bool haveLPAE;
89 bool haveVirtualization;
90 bool haveCrypto;
91 bool haveLargeAsid64;
92 uint8_t physAddrRange;
93
94 /**
95 * If true, accesses to IMPLEMENTATION DEFINED registers are treated
96 * as NOP hence not causing UNDEFINED INSTRUCTION.
97 */
98 bool impdefAsNop;
99
100 /** MiscReg metadata **/
101 struct MiscRegLUTEntry {
102 uint32_t lower; // Lower half mapped to this register
103 uint32_t upper; // Upper half mapped to this register
104 uint64_t _reset; // value taken on reset (i.e. initialization)
105 uint64_t _res0; // reserved
106 uint64_t _res1; // reserved
107 uint64_t _raz; // read as zero (fixed at 0)
108 uint64_t _rao; // read as one (fixed at 1)
109 public:
110 MiscRegLUTEntry() :
111 lower(0), upper(0),
112 _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
113 uint64_t reset() const { return _reset; }
114 uint64_t res0() const { return _res0; }
115 uint64_t res1() const { return _res1; }
116 uint64_t raz() const { return _raz; }
117 uint64_t rao() const { return _rao; }
118 // raz/rao implies writes ignored
119 uint64_t wi() const { return _raz | _rao; }
120 };
121
122 /** Metadata table accessible via the value of the register */
123 static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
124
125 class MiscRegLUTEntryInitializer {
126 struct MiscRegLUTEntry &entry;
127 std::bitset<NUM_MISCREG_INFOS> &info;
128 typedef const MiscRegLUTEntryInitializer& chain;
129 public:
130 chain mapsTo(uint32_t l, uint32_t u = 0) const {
131 entry.lower = l;
132 entry.upper = u;
133 return *this;
134 }
135 chain res0(uint64_t mask) const {
136 entry._res0 = mask;
137 return *this;
138 }
139 chain res1(uint64_t mask) const {
140 entry._res1 = mask;
141 return *this;
142 }
143 chain raz(uint64_t mask) const {
144 entry._raz = mask;
145 return *this;
146 }
147 chain rao(uint64_t mask) const {
148 entry._rao = mask;
149 return *this;
150 }
151 chain implemented(bool v = true) const {
152 info[MISCREG_IMPLEMENTED] = v;
153 return *this;
154 }
155 chain unimplemented() const {
156 return implemented(false);
157 }
158 chain unverifiable(bool v = true) const {
159 info[MISCREG_UNVERIFIABLE] = v;
160 return *this;
161 }
162 chain warnNotFail(bool v = true) const {
163 info[MISCREG_WARN_NOT_FAIL] = v;
164 return *this;
165 }
166 chain mutex(bool v = true) const {
167 info[MISCREG_MUTEX] = v;
168 return *this;
169 }
170 chain banked(bool v = true) const {
171 info[MISCREG_BANKED] = v;
172 return *this;
173 }
174 chain bankedChild(bool v = true) const {
175 info[MISCREG_BANKED_CHILD] = v;
176 return *this;
177 }
178 chain userNonSecureRead(bool v = true) const {
179 info[MISCREG_USR_NS_RD] = v;
180 return *this;
181 }
182 chain userNonSecureWrite(bool v = true) const {
183 info[MISCREG_USR_NS_WR] = v;
184 return *this;
185 }
186 chain userSecureRead(bool v = true) const {
187 info[MISCREG_USR_S_RD] = v;
188 return *this;
189 }
190 chain userSecureWrite(bool v = true) const {
191 info[MISCREG_USR_S_WR] = v;
192 return *this;
193 }
194 chain user(bool v = true) const {
195 userNonSecureRead(v);
196 userNonSecureWrite(v);
197 userSecureRead(v);
198 userSecureWrite(v);
199 return *this;
200 }
201 chain privNonSecureRead(bool v = true) const {
202 info[MISCREG_PRI_NS_RD] = v;
203 return *this;
204 }
205 chain privNonSecureWrite(bool v = true) const {
206 info[MISCREG_PRI_NS_WR] = v;
207 return *this;
208 }
209 chain privNonSecure(bool v = true) const {
210 privNonSecureRead(v);
211 privNonSecureWrite(v);
212 return *this;
213 }
214 chain privSecureRead(bool v = true) const {
215 info[MISCREG_PRI_S_RD] = v;
216 return *this;
217 }
218 chain privSecureWrite(bool v = true) const {
219 info[MISCREG_PRI_S_WR] = v;
220 return *this;
221 }
222 chain privSecure(bool v = true) const {
223 privSecureRead(v);
224 privSecureWrite(v);
225 return *this;
226 }
227 chain priv(bool v = true) const {
228 privSecure(v);
229 privNonSecure(v);
230 return *this;
231 }
1/*
2 * Copyright (c) 2010, 2012-2018 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/isa_device.hh"
47#include "arch/arm/miscregs.hh"
48#include "arch/arm/registers.hh"
49#include "arch/arm/system.hh"
50#include "arch/arm/tlb.hh"
51#include "arch/arm/types.hh"
52#include "arch/generic/traits.hh"
53#include "debug/Checkpoint.hh"
54#include "enums/VecRegRenameMode.hh"
55#include "sim/sim_object.hh"
56#include "enums/DecoderFlavour.hh"
57
58struct ArmISAParams;
59struct DummyArmISADeviceParams;
60class ThreadContext;
61class Checkpoint;
62class EventManager;
63
64namespace ArmISA
65{
66 class ISA : public SimObject
67 {
68 protected:
69 // Parent system
70 ArmSystem *system;
71
72 // Micro Architecture
73 const Enums::DecoderFlavour _decoderFlavour;
74 const Enums::VecRegRenameMode _vecRegRenameMode;
75
76 /** Dummy device for to handle non-existing ISA devices */
77 DummyISADevice dummyDevice;
78
79 // PMU belonging to this ISA
80 BaseISADevice *pmu;
81
82 // Generic timer interface belonging to this ISA
83 std::unique_ptr<BaseISADevice> timer;
84
85 // Cached copies of system-level properties
86 bool highestELIs64;
87 bool haveSecurity;
88 bool haveLPAE;
89 bool haveVirtualization;
90 bool haveCrypto;
91 bool haveLargeAsid64;
92 uint8_t physAddrRange;
93
94 /**
95 * If true, accesses to IMPLEMENTATION DEFINED registers are treated
96 * as NOP hence not causing UNDEFINED INSTRUCTION.
97 */
98 bool impdefAsNop;
99
100 /** MiscReg metadata **/
101 struct MiscRegLUTEntry {
102 uint32_t lower; // Lower half mapped to this register
103 uint32_t upper; // Upper half mapped to this register
104 uint64_t _reset; // value taken on reset (i.e. initialization)
105 uint64_t _res0; // reserved
106 uint64_t _res1; // reserved
107 uint64_t _raz; // read as zero (fixed at 0)
108 uint64_t _rao; // read as one (fixed at 1)
109 public:
110 MiscRegLUTEntry() :
111 lower(0), upper(0),
112 _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
113 uint64_t reset() const { return _reset; }
114 uint64_t res0() const { return _res0; }
115 uint64_t res1() const { return _res1; }
116 uint64_t raz() const { return _raz; }
117 uint64_t rao() const { return _rao; }
118 // raz/rao implies writes ignored
119 uint64_t wi() const { return _raz | _rao; }
120 };
121
122 /** Metadata table accessible via the value of the register */
123 static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
124
125 class MiscRegLUTEntryInitializer {
126 struct MiscRegLUTEntry &entry;
127 std::bitset<NUM_MISCREG_INFOS> &info;
128 typedef const MiscRegLUTEntryInitializer& chain;
129 public:
130 chain mapsTo(uint32_t l, uint32_t u = 0) const {
131 entry.lower = l;
132 entry.upper = u;
133 return *this;
134 }
135 chain res0(uint64_t mask) const {
136 entry._res0 = mask;
137 return *this;
138 }
139 chain res1(uint64_t mask) const {
140 entry._res1 = mask;
141 return *this;
142 }
143 chain raz(uint64_t mask) const {
144 entry._raz = mask;
145 return *this;
146 }
147 chain rao(uint64_t mask) const {
148 entry._rao = mask;
149 return *this;
150 }
151 chain implemented(bool v = true) const {
152 info[MISCREG_IMPLEMENTED] = v;
153 return *this;
154 }
155 chain unimplemented() const {
156 return implemented(false);
157 }
158 chain unverifiable(bool v = true) const {
159 info[MISCREG_UNVERIFIABLE] = v;
160 return *this;
161 }
162 chain warnNotFail(bool v = true) const {
163 info[MISCREG_WARN_NOT_FAIL] = v;
164 return *this;
165 }
166 chain mutex(bool v = true) const {
167 info[MISCREG_MUTEX] = v;
168 return *this;
169 }
170 chain banked(bool v = true) const {
171 info[MISCREG_BANKED] = v;
172 return *this;
173 }
174 chain bankedChild(bool v = true) const {
175 info[MISCREG_BANKED_CHILD] = v;
176 return *this;
177 }
178 chain userNonSecureRead(bool v = true) const {
179 info[MISCREG_USR_NS_RD] = v;
180 return *this;
181 }
182 chain userNonSecureWrite(bool v = true) const {
183 info[MISCREG_USR_NS_WR] = v;
184 return *this;
185 }
186 chain userSecureRead(bool v = true) const {
187 info[MISCREG_USR_S_RD] = v;
188 return *this;
189 }
190 chain userSecureWrite(bool v = true) const {
191 info[MISCREG_USR_S_WR] = v;
192 return *this;
193 }
194 chain user(bool v = true) const {
195 userNonSecureRead(v);
196 userNonSecureWrite(v);
197 userSecureRead(v);
198 userSecureWrite(v);
199 return *this;
200 }
201 chain privNonSecureRead(bool v = true) const {
202 info[MISCREG_PRI_NS_RD] = v;
203 return *this;
204 }
205 chain privNonSecureWrite(bool v = true) const {
206 info[MISCREG_PRI_NS_WR] = v;
207 return *this;
208 }
209 chain privNonSecure(bool v = true) const {
210 privNonSecureRead(v);
211 privNonSecureWrite(v);
212 return *this;
213 }
214 chain privSecureRead(bool v = true) const {
215 info[MISCREG_PRI_S_RD] = v;
216 return *this;
217 }
218 chain privSecureWrite(bool v = true) const {
219 info[MISCREG_PRI_S_WR] = v;
220 return *this;
221 }
222 chain privSecure(bool v = true) const {
223 privSecureRead(v);
224 privSecureWrite(v);
225 return *this;
226 }
227 chain priv(bool v = true) const {
228 privSecure(v);
229 privNonSecure(v);
230 return *this;
231 }
232 chain privRead(bool v = true) const {
233 privSecureRead(v);
234 privNonSecureRead(v);
235 return *this;
236 }
232 chain hypRead(bool v = true) const {
233 info[MISCREG_HYP_RD] = v;
234 return *this;
235 }
236 chain hypWrite(bool v = true) const {
237 info[MISCREG_HYP_WR] = v;
238 return *this;
239 }
240 chain hyp(bool v = true) const {
241 hypRead(v);
242 hypWrite(v);
243 return *this;
244 }
245 chain monSecureRead(bool v = true) const {
246 info[MISCREG_MON_NS0_RD] = v;
247 return *this;
248 }
249 chain monSecureWrite(bool v = true) const {
250 info[MISCREG_MON_NS0_WR] = v;
251 return *this;
252 }
253 chain monNonSecureRead(bool v = true) const {
254 info[MISCREG_MON_NS1_RD] = v;
255 return *this;
256 }
257 chain monNonSecureWrite(bool v = true) const {
258 info[MISCREG_MON_NS1_WR] = v;
259 return *this;
260 }
261 chain mon(bool v = true) const {
262 monSecureRead(v);
263 monSecureWrite(v);
264 monNonSecureRead(v);
265 monNonSecureWrite(v);
266 return *this;
267 }
268 chain monSecure(bool v = true) const {
269 monSecureRead(v);
270 monSecureWrite(v);
271 return *this;
272 }
273 chain monNonSecure(bool v = true) const {
274 monNonSecureRead(v);
275 monNonSecureWrite(v);
276 return *this;
277 }
278 chain allPrivileges(bool v = true) const {
279 userNonSecureRead(v);
280 userNonSecureWrite(v);
281 userSecureRead(v);
282 userSecureWrite(v);
283 privNonSecureRead(v);
284 privNonSecureWrite(v);
285 privSecureRead(v);
286 privSecureWrite(v);
287 hypRead(v);
288 hypWrite(v);
289 monSecureRead(v);
290 monSecureWrite(v);
291 monNonSecureRead(v);
292 monNonSecureWrite(v);
293 return *this;
294 }
295 chain nonSecure(bool v = true) const {
296 userNonSecureRead(v);
297 userNonSecureWrite(v);
298 privNonSecureRead(v);
299 privNonSecureWrite(v);
300 hypRead(v);
301 hypWrite(v);
302 monNonSecureRead(v);
303 monNonSecureWrite(v);
304 return *this;
305 }
306 chain secure(bool v = true) const {
307 userSecureRead(v);
308 userSecureWrite(v);
309 privSecureRead(v);
310 privSecureWrite(v);
311 monSecureRead(v);
312 monSecureWrite(v);
313 return *this;
314 }
315 chain reads(bool v) const {
316 userNonSecureRead(v);
317 userSecureRead(v);
318 privNonSecureRead(v);
319 privSecureRead(v);
320 hypRead(v);
321 monSecureRead(v);
322 monNonSecureRead(v);
323 return *this;
324 }
325 chain writes(bool v) const {
326 userNonSecureWrite(v);
327 userSecureWrite(v);
328 privNonSecureWrite(v);
329 privSecureWrite(v);
330 hypWrite(v);
331 monSecureWrite(v);
332 monNonSecureWrite(v);
333 return *this;
334 }
335 chain exceptUserMode() const {
336 user(0);
337 return *this;
338 }
339 MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
340 std::bitset<NUM_MISCREG_INFOS> &i)
341 : entry(e),
342 info(i)
343 {
344 // force unimplemented registers to be thusly declared
345 implemented(1);
346 }
347 };
348
349 const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
350 return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
351 miscRegInfo[reg]);
352 }
353
354 void initializeMiscRegMetadata();
355
356 MiscReg miscRegs[NumMiscRegs];
357 const IntRegIndex *intRegMap;
358
359 void
360 updateRegMap(CPSR cpsr)
361 {
362 if (cpsr.width == 0) {
363 intRegMap = IntReg64Map;
364 } else {
365 switch (cpsr.mode) {
366 case MODE_USER:
367 case MODE_SYSTEM:
368 intRegMap = IntRegUsrMap;
369 break;
370 case MODE_FIQ:
371 intRegMap = IntRegFiqMap;
372 break;
373 case MODE_IRQ:
374 intRegMap = IntRegIrqMap;
375 break;
376 case MODE_SVC:
377 intRegMap = IntRegSvcMap;
378 break;
379 case MODE_MON:
380 intRegMap = IntRegMonMap;
381 break;
382 case MODE_ABORT:
383 intRegMap = IntRegAbtMap;
384 break;
385 case MODE_HYP:
386 intRegMap = IntRegHypMap;
387 break;
388 case MODE_UNDEFINED:
389 intRegMap = IntRegUndMap;
390 break;
391 default:
392 panic("Unrecognized mode setting in CPSR.\n");
393 }
394 }
395 }
396
397 BaseISADevice &getGenericTimer(ThreadContext *tc);
398
399
400 private:
401 inline void assert32(ThreadContext *tc) {
402 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
403 assert(cpsr.width);
404 }
405
406 inline void assert64(ThreadContext *tc) {
407 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
408 assert(!cpsr.width);
409 }
410
411 public:
412 void clear();
413
414 protected:
415 void clear32(const ArmISAParams *p, const SCTLR &sctlr_rst);
416 void clear64(const ArmISAParams *p);
417 void initID32(const ArmISAParams *p);
418 void initID64(const ArmISAParams *p);
419
420 public:
421 MiscReg readMiscRegNoEffect(int misc_reg) const;
422 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
423 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
424 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
425
426 RegId
427 flattenRegId(const RegId& regId) const
428 {
429 switch (regId.classValue()) {
430 case IntRegClass:
431 return RegId(IntRegClass, flattenIntIndex(regId.index()));
432 case FloatRegClass:
433 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
434 case VecRegClass:
435 return RegId(VecRegClass, flattenVecIndex(regId.index()));
436 case VecElemClass:
437 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
438 case CCRegClass:
439 return RegId(CCRegClass, flattenCCIndex(regId.index()));
440 case MiscRegClass:
441 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
442 }
443 return RegId();
444 }
445
446 int
447 flattenIntIndex(int reg) const
448 {
449 assert(reg >= 0);
450 if (reg < NUM_ARCH_INTREGS) {
451 return intRegMap[reg];
452 } else if (reg < NUM_INTREGS) {
453 return reg;
454 } else if (reg == INTREG_SPX) {
455 CPSR cpsr = miscRegs[MISCREG_CPSR];
456 ExceptionLevel el = opModeToEL(
457 (OperatingMode) (uint8_t) cpsr.mode);
458 if (!cpsr.sp && el != EL0)
459 return INTREG_SP0;
460 switch (el) {
461 case EL3:
462 return INTREG_SP3;
463 case EL2:
464 return INTREG_SP2;
465 case EL1:
466 return INTREG_SP1;
467 case EL0:
468 return INTREG_SP0;
469 default:
470 panic("Invalid exception level");
471 return 0; // Never happens.
472 }
473 } else {
474 return flattenIntRegModeIndex(reg);
475 }
476 }
477
478 int
479 flattenFloatIndex(int reg) const
480 {
481 assert(reg >= 0);
482 return reg;
483 }
484
485 int
486 flattenVecIndex(int reg) const
487 {
488 assert(reg >= 0);
489 return reg;
490 }
491
492 int
493 flattenVecElemIndex(int reg) const
494 {
495 assert(reg >= 0);
496 return reg;
497 }
498
499 int
500 flattenCCIndex(int reg) const
501 {
502 assert(reg >= 0);
503 return reg;
504 }
505
506 int
507 flattenMiscIndex(int reg) const
508 {
509 assert(reg >= 0);
510 int flat_idx = reg;
511
512 if (reg == MISCREG_SPSR) {
513 CPSR cpsr = miscRegs[MISCREG_CPSR];
514 switch (cpsr.mode) {
515 case MODE_EL0T:
516 warn("User mode does not have SPSR\n");
517 flat_idx = MISCREG_SPSR;
518 break;
519 case MODE_EL1T:
520 case MODE_EL1H:
521 flat_idx = MISCREG_SPSR_EL1;
522 break;
523 case MODE_EL2T:
524 case MODE_EL2H:
525 flat_idx = MISCREG_SPSR_EL2;
526 break;
527 case MODE_EL3T:
528 case MODE_EL3H:
529 flat_idx = MISCREG_SPSR_EL3;
530 break;
531 case MODE_USER:
532 warn("User mode does not have SPSR\n");
533 flat_idx = MISCREG_SPSR;
534 break;
535 case MODE_FIQ:
536 flat_idx = MISCREG_SPSR_FIQ;
537 break;
538 case MODE_IRQ:
539 flat_idx = MISCREG_SPSR_IRQ;
540 break;
541 case MODE_SVC:
542 flat_idx = MISCREG_SPSR_SVC;
543 break;
544 case MODE_MON:
545 flat_idx = MISCREG_SPSR_MON;
546 break;
547 case MODE_ABORT:
548 flat_idx = MISCREG_SPSR_ABT;
549 break;
550 case MODE_HYP:
551 flat_idx = MISCREG_SPSR_HYP;
552 break;
553 case MODE_UNDEFINED:
554 flat_idx = MISCREG_SPSR_UND;
555 break;
556 default:
557 warn("Trying to access SPSR in an invalid mode: %d\n",
558 cpsr.mode);
559 flat_idx = MISCREG_SPSR;
560 break;
561 }
562 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
563 // Mutually exclusive CP15 register
564 switch (reg) {
565 case MISCREG_PRRR_MAIR0:
566 case MISCREG_PRRR_MAIR0_NS:
567 case MISCREG_PRRR_MAIR0_S:
568 {
569 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
570 // If the muxed reg has been flattened, work out the
571 // offset and apply it to the unmuxed reg
572 int idxOffset = reg - MISCREG_PRRR_MAIR0;
573 if (ttbcr.eae)
574 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
575 idxOffset);
576 else
577 flat_idx = flattenMiscIndex(MISCREG_PRRR +
578 idxOffset);
579 }
580 break;
581 case MISCREG_NMRR_MAIR1:
582 case MISCREG_NMRR_MAIR1_NS:
583 case MISCREG_NMRR_MAIR1_S:
584 {
585 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
586 // If the muxed reg has been flattened, work out the
587 // offset and apply it to the unmuxed reg
588 int idxOffset = reg - MISCREG_NMRR_MAIR1;
589 if (ttbcr.eae)
590 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
591 idxOffset);
592 else
593 flat_idx = flattenMiscIndex(MISCREG_NMRR +
594 idxOffset);
595 }
596 break;
597 case MISCREG_PMXEVTYPER_PMCCFILTR:
598 {
599 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
600 if (pmselr.sel == 31)
601 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
602 else
603 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
604 }
605 break;
606 default:
607 panic("Unrecognized misc. register.\n");
608 break;
609 }
610 } else {
611 if (miscRegInfo[reg][MISCREG_BANKED]) {
612 bool secureReg = haveSecurity && !highestELIs64 &&
613 inSecureState(miscRegs[MISCREG_SCR],
614 miscRegs[MISCREG_CPSR]);
615 flat_idx += secureReg ? 2 : 1;
616 }
617 }
618 return flat_idx;
619 }
620
621 std::pair<int,int> getMiscIndices(int misc_reg) const
622 {
623 // Note: indexes of AArch64 registers are left unchanged
624 int flat_idx = flattenMiscIndex(misc_reg);
625
626 if (lookUpMiscReg[flat_idx].lower == 0) {
627 return std::make_pair(flat_idx, 0);
628 }
629
630 // do additional S/NS flattenings if mapped to NS while in S
631 bool S = haveSecurity && !highestELIs64 &&
632 inSecureState(miscRegs[MISCREG_SCR],
633 miscRegs[MISCREG_CPSR]);
634 int lower = lookUpMiscReg[flat_idx].lower;
635 int upper = lookUpMiscReg[flat_idx].upper;
636 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
637 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
638 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
639 return std::make_pair(lower, upper);
640 }
641
642 void serialize(CheckpointOut &cp) const
643 {
644 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
645 SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
646
647 SERIALIZE_SCALAR(highestELIs64);
648 SERIALIZE_SCALAR(haveSecurity);
649 SERIALIZE_SCALAR(haveLPAE);
650 SERIALIZE_SCALAR(haveVirtualization);
651 SERIALIZE_SCALAR(haveLargeAsid64);
652 SERIALIZE_SCALAR(physAddrRange);
653 }
654 void unserialize(CheckpointIn &cp)
655 {
656 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
657 UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
658 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
659 updateRegMap(tmp_cpsr);
660
661 UNSERIALIZE_SCALAR(highestELIs64);
662 UNSERIALIZE_SCALAR(haveSecurity);
663 UNSERIALIZE_SCALAR(haveLPAE);
664 UNSERIALIZE_SCALAR(haveVirtualization);
665 UNSERIALIZE_SCALAR(haveLargeAsid64);
666 UNSERIALIZE_SCALAR(physAddrRange);
667 }
668
669 void startup(ThreadContext *tc);
670
671 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
672
673 Enums::VecRegRenameMode
674 vecRegRenameMode() const
675 {
676 return _vecRegRenameMode;
677 }
678
679 /// Explicitly import the otherwise hidden startup
680 using SimObject::startup;
681
682 typedef ArmISAParams Params;
683
684 const Params *params() const;
685
686 ISA(Params *p);
687 };
688}
689
690template<>
691struct initRenameMode<ArmISA::ISA>
692{
693 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
694 {
695 return isa->vecRegRenameMode();
696 }
697 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
698 {
699 return mode(isa1) == mode(isa2);
700 }
701};
702
703#endif
237 chain hypRead(bool v = true) const {
238 info[MISCREG_HYP_RD] = v;
239 return *this;
240 }
241 chain hypWrite(bool v = true) const {
242 info[MISCREG_HYP_WR] = v;
243 return *this;
244 }
245 chain hyp(bool v = true) const {
246 hypRead(v);
247 hypWrite(v);
248 return *this;
249 }
250 chain monSecureRead(bool v = true) const {
251 info[MISCREG_MON_NS0_RD] = v;
252 return *this;
253 }
254 chain monSecureWrite(bool v = true) const {
255 info[MISCREG_MON_NS0_WR] = v;
256 return *this;
257 }
258 chain monNonSecureRead(bool v = true) const {
259 info[MISCREG_MON_NS1_RD] = v;
260 return *this;
261 }
262 chain monNonSecureWrite(bool v = true) const {
263 info[MISCREG_MON_NS1_WR] = v;
264 return *this;
265 }
266 chain mon(bool v = true) const {
267 monSecureRead(v);
268 monSecureWrite(v);
269 monNonSecureRead(v);
270 monNonSecureWrite(v);
271 return *this;
272 }
273 chain monSecure(bool v = true) const {
274 monSecureRead(v);
275 monSecureWrite(v);
276 return *this;
277 }
278 chain monNonSecure(bool v = true) const {
279 monNonSecureRead(v);
280 monNonSecureWrite(v);
281 return *this;
282 }
283 chain allPrivileges(bool v = true) const {
284 userNonSecureRead(v);
285 userNonSecureWrite(v);
286 userSecureRead(v);
287 userSecureWrite(v);
288 privNonSecureRead(v);
289 privNonSecureWrite(v);
290 privSecureRead(v);
291 privSecureWrite(v);
292 hypRead(v);
293 hypWrite(v);
294 monSecureRead(v);
295 monSecureWrite(v);
296 monNonSecureRead(v);
297 monNonSecureWrite(v);
298 return *this;
299 }
300 chain nonSecure(bool v = true) const {
301 userNonSecureRead(v);
302 userNonSecureWrite(v);
303 privNonSecureRead(v);
304 privNonSecureWrite(v);
305 hypRead(v);
306 hypWrite(v);
307 monNonSecureRead(v);
308 monNonSecureWrite(v);
309 return *this;
310 }
311 chain secure(bool v = true) const {
312 userSecureRead(v);
313 userSecureWrite(v);
314 privSecureRead(v);
315 privSecureWrite(v);
316 monSecureRead(v);
317 monSecureWrite(v);
318 return *this;
319 }
320 chain reads(bool v) const {
321 userNonSecureRead(v);
322 userSecureRead(v);
323 privNonSecureRead(v);
324 privSecureRead(v);
325 hypRead(v);
326 monSecureRead(v);
327 monNonSecureRead(v);
328 return *this;
329 }
330 chain writes(bool v) const {
331 userNonSecureWrite(v);
332 userSecureWrite(v);
333 privNonSecureWrite(v);
334 privSecureWrite(v);
335 hypWrite(v);
336 monSecureWrite(v);
337 monNonSecureWrite(v);
338 return *this;
339 }
340 chain exceptUserMode() const {
341 user(0);
342 return *this;
343 }
344 MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
345 std::bitset<NUM_MISCREG_INFOS> &i)
346 : entry(e),
347 info(i)
348 {
349 // force unimplemented registers to be thusly declared
350 implemented(1);
351 }
352 };
353
354 const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
355 return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
356 miscRegInfo[reg]);
357 }
358
359 void initializeMiscRegMetadata();
360
361 MiscReg miscRegs[NumMiscRegs];
362 const IntRegIndex *intRegMap;
363
364 void
365 updateRegMap(CPSR cpsr)
366 {
367 if (cpsr.width == 0) {
368 intRegMap = IntReg64Map;
369 } else {
370 switch (cpsr.mode) {
371 case MODE_USER:
372 case MODE_SYSTEM:
373 intRegMap = IntRegUsrMap;
374 break;
375 case MODE_FIQ:
376 intRegMap = IntRegFiqMap;
377 break;
378 case MODE_IRQ:
379 intRegMap = IntRegIrqMap;
380 break;
381 case MODE_SVC:
382 intRegMap = IntRegSvcMap;
383 break;
384 case MODE_MON:
385 intRegMap = IntRegMonMap;
386 break;
387 case MODE_ABORT:
388 intRegMap = IntRegAbtMap;
389 break;
390 case MODE_HYP:
391 intRegMap = IntRegHypMap;
392 break;
393 case MODE_UNDEFINED:
394 intRegMap = IntRegUndMap;
395 break;
396 default:
397 panic("Unrecognized mode setting in CPSR.\n");
398 }
399 }
400 }
401
402 BaseISADevice &getGenericTimer(ThreadContext *tc);
403
404
405 private:
406 inline void assert32(ThreadContext *tc) {
407 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
408 assert(cpsr.width);
409 }
410
411 inline void assert64(ThreadContext *tc) {
412 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
413 assert(!cpsr.width);
414 }
415
416 public:
417 void clear();
418
419 protected:
420 void clear32(const ArmISAParams *p, const SCTLR &sctlr_rst);
421 void clear64(const ArmISAParams *p);
422 void initID32(const ArmISAParams *p);
423 void initID64(const ArmISAParams *p);
424
425 public:
426 MiscReg readMiscRegNoEffect(int misc_reg) const;
427 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
428 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
429 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
430
431 RegId
432 flattenRegId(const RegId& regId) const
433 {
434 switch (regId.classValue()) {
435 case IntRegClass:
436 return RegId(IntRegClass, flattenIntIndex(regId.index()));
437 case FloatRegClass:
438 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
439 case VecRegClass:
440 return RegId(VecRegClass, flattenVecIndex(regId.index()));
441 case VecElemClass:
442 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
443 case CCRegClass:
444 return RegId(CCRegClass, flattenCCIndex(regId.index()));
445 case MiscRegClass:
446 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
447 }
448 return RegId();
449 }
450
451 int
452 flattenIntIndex(int reg) const
453 {
454 assert(reg >= 0);
455 if (reg < NUM_ARCH_INTREGS) {
456 return intRegMap[reg];
457 } else if (reg < NUM_INTREGS) {
458 return reg;
459 } else if (reg == INTREG_SPX) {
460 CPSR cpsr = miscRegs[MISCREG_CPSR];
461 ExceptionLevel el = opModeToEL(
462 (OperatingMode) (uint8_t) cpsr.mode);
463 if (!cpsr.sp && el != EL0)
464 return INTREG_SP0;
465 switch (el) {
466 case EL3:
467 return INTREG_SP3;
468 case EL2:
469 return INTREG_SP2;
470 case EL1:
471 return INTREG_SP1;
472 case EL0:
473 return INTREG_SP0;
474 default:
475 panic("Invalid exception level");
476 return 0; // Never happens.
477 }
478 } else {
479 return flattenIntRegModeIndex(reg);
480 }
481 }
482
483 int
484 flattenFloatIndex(int reg) const
485 {
486 assert(reg >= 0);
487 return reg;
488 }
489
490 int
491 flattenVecIndex(int reg) const
492 {
493 assert(reg >= 0);
494 return reg;
495 }
496
497 int
498 flattenVecElemIndex(int reg) const
499 {
500 assert(reg >= 0);
501 return reg;
502 }
503
504 int
505 flattenCCIndex(int reg) const
506 {
507 assert(reg >= 0);
508 return reg;
509 }
510
511 int
512 flattenMiscIndex(int reg) const
513 {
514 assert(reg >= 0);
515 int flat_idx = reg;
516
517 if (reg == MISCREG_SPSR) {
518 CPSR cpsr = miscRegs[MISCREG_CPSR];
519 switch (cpsr.mode) {
520 case MODE_EL0T:
521 warn("User mode does not have SPSR\n");
522 flat_idx = MISCREG_SPSR;
523 break;
524 case MODE_EL1T:
525 case MODE_EL1H:
526 flat_idx = MISCREG_SPSR_EL1;
527 break;
528 case MODE_EL2T:
529 case MODE_EL2H:
530 flat_idx = MISCREG_SPSR_EL2;
531 break;
532 case MODE_EL3T:
533 case MODE_EL3H:
534 flat_idx = MISCREG_SPSR_EL3;
535 break;
536 case MODE_USER:
537 warn("User mode does not have SPSR\n");
538 flat_idx = MISCREG_SPSR;
539 break;
540 case MODE_FIQ:
541 flat_idx = MISCREG_SPSR_FIQ;
542 break;
543 case MODE_IRQ:
544 flat_idx = MISCREG_SPSR_IRQ;
545 break;
546 case MODE_SVC:
547 flat_idx = MISCREG_SPSR_SVC;
548 break;
549 case MODE_MON:
550 flat_idx = MISCREG_SPSR_MON;
551 break;
552 case MODE_ABORT:
553 flat_idx = MISCREG_SPSR_ABT;
554 break;
555 case MODE_HYP:
556 flat_idx = MISCREG_SPSR_HYP;
557 break;
558 case MODE_UNDEFINED:
559 flat_idx = MISCREG_SPSR_UND;
560 break;
561 default:
562 warn("Trying to access SPSR in an invalid mode: %d\n",
563 cpsr.mode);
564 flat_idx = MISCREG_SPSR;
565 break;
566 }
567 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
568 // Mutually exclusive CP15 register
569 switch (reg) {
570 case MISCREG_PRRR_MAIR0:
571 case MISCREG_PRRR_MAIR0_NS:
572 case MISCREG_PRRR_MAIR0_S:
573 {
574 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
575 // If the muxed reg has been flattened, work out the
576 // offset and apply it to the unmuxed reg
577 int idxOffset = reg - MISCREG_PRRR_MAIR0;
578 if (ttbcr.eae)
579 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
580 idxOffset);
581 else
582 flat_idx = flattenMiscIndex(MISCREG_PRRR +
583 idxOffset);
584 }
585 break;
586 case MISCREG_NMRR_MAIR1:
587 case MISCREG_NMRR_MAIR1_NS:
588 case MISCREG_NMRR_MAIR1_S:
589 {
590 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
591 // If the muxed reg has been flattened, work out the
592 // offset and apply it to the unmuxed reg
593 int idxOffset = reg - MISCREG_NMRR_MAIR1;
594 if (ttbcr.eae)
595 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
596 idxOffset);
597 else
598 flat_idx = flattenMiscIndex(MISCREG_NMRR +
599 idxOffset);
600 }
601 break;
602 case MISCREG_PMXEVTYPER_PMCCFILTR:
603 {
604 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
605 if (pmselr.sel == 31)
606 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
607 else
608 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
609 }
610 break;
611 default:
612 panic("Unrecognized misc. register.\n");
613 break;
614 }
615 } else {
616 if (miscRegInfo[reg][MISCREG_BANKED]) {
617 bool secureReg = haveSecurity && !highestELIs64 &&
618 inSecureState(miscRegs[MISCREG_SCR],
619 miscRegs[MISCREG_CPSR]);
620 flat_idx += secureReg ? 2 : 1;
621 }
622 }
623 return flat_idx;
624 }
625
626 std::pair<int,int> getMiscIndices(int misc_reg) const
627 {
628 // Note: indexes of AArch64 registers are left unchanged
629 int flat_idx = flattenMiscIndex(misc_reg);
630
631 if (lookUpMiscReg[flat_idx].lower == 0) {
632 return std::make_pair(flat_idx, 0);
633 }
634
635 // do additional S/NS flattenings if mapped to NS while in S
636 bool S = haveSecurity && !highestELIs64 &&
637 inSecureState(miscRegs[MISCREG_SCR],
638 miscRegs[MISCREG_CPSR]);
639 int lower = lookUpMiscReg[flat_idx].lower;
640 int upper = lookUpMiscReg[flat_idx].upper;
641 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
642 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
643 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
644 return std::make_pair(lower, upper);
645 }
646
647 void serialize(CheckpointOut &cp) const
648 {
649 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
650 SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
651
652 SERIALIZE_SCALAR(highestELIs64);
653 SERIALIZE_SCALAR(haveSecurity);
654 SERIALIZE_SCALAR(haveLPAE);
655 SERIALIZE_SCALAR(haveVirtualization);
656 SERIALIZE_SCALAR(haveLargeAsid64);
657 SERIALIZE_SCALAR(physAddrRange);
658 }
659 void unserialize(CheckpointIn &cp)
660 {
661 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
662 UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
663 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
664 updateRegMap(tmp_cpsr);
665
666 UNSERIALIZE_SCALAR(highestELIs64);
667 UNSERIALIZE_SCALAR(haveSecurity);
668 UNSERIALIZE_SCALAR(haveLPAE);
669 UNSERIALIZE_SCALAR(haveVirtualization);
670 UNSERIALIZE_SCALAR(haveLargeAsid64);
671 UNSERIALIZE_SCALAR(physAddrRange);
672 }
673
674 void startup(ThreadContext *tc);
675
676 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
677
678 Enums::VecRegRenameMode
679 vecRegRenameMode() const
680 {
681 return _vecRegRenameMode;
682 }
683
684 /// Explicitly import the otherwise hidden startup
685 using SimObject::startup;
686
687 typedef ArmISAParams Params;
688
689 const Params *params() const;
690
691 ISA(Params *p);
692 };
693}
694
695template<>
696struct initRenameMode<ArmISA::ISA>
697{
698 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
699 {
700 return isa->vecRegRenameMode();
701 }
702 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
703 {
704 return mode(isa1) == mode(isa2);
705 }
706};
707
708#endif