isa.hh (12109:f29e9c5418aa) isa.hh (12477:3d6c49bc7290)
1/*
1/*
2 * Copyright (c) 2010, 2012-2016 ARM Limited
2 * Copyright (c) 2010, 2012-2017 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/registers.hh"
48#include "arch/arm/system.hh"
49#include "arch/arm/tlb.hh"
50#include "arch/arm/types.hh"
51#include "arch/generic/traits.hh"
52#include "debug/Checkpoint.hh"
53#include "enums/VecRegRenameMode.hh"
54#include "sim/sim_object.hh"
55#include "enums/DecoderFlavour.hh"
56
57struct ArmISAParams;
58struct DummyArmISADeviceParams;
59class ThreadContext;
60class Checkpoint;
61class EventManager;
62
63namespace ArmISA
64{
65 class ISA : public SimObject
66 {
67 protected:
68 // Parent system
69 ArmSystem *system;
70
71 // Micro Architecture
72 const Enums::DecoderFlavour _decoderFlavour;
73 const Enums::VecRegRenameMode _vecRegRenameMode;
74
75 /** Dummy device for to handle non-existing ISA devices */
76 DummyISADevice dummyDevice;
77
78 // PMU belonging to this ISA
79 BaseISADevice *pmu;
80
81 // Generic timer interface belonging to this ISA
82 std::unique_ptr<BaseISADevice> timer;
83
84 // Cached copies of system-level properties
85 bool highestELIs64;
86 bool haveSecurity;
87 bool haveLPAE;
88 bool haveVirtualization;
89 bool haveLargeAsid64;
90 uint8_t physAddrRange64;
91
92 /** Register translation entry used in lookUpMiscReg */
93 struct MiscRegLUTEntry {
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/registers.hh"
48#include "arch/arm/system.hh"
49#include "arch/arm/tlb.hh"
50#include "arch/arm/types.hh"
51#include "arch/generic/traits.hh"
52#include "debug/Checkpoint.hh"
53#include "enums/VecRegRenameMode.hh"
54#include "sim/sim_object.hh"
55#include "enums/DecoderFlavour.hh"
56
57struct ArmISAParams;
58struct DummyArmISADeviceParams;
59class ThreadContext;
60class Checkpoint;
61class EventManager;
62
63namespace ArmISA
64{
65 class ISA : public SimObject
66 {
67 protected:
68 // Parent system
69 ArmSystem *system;
70
71 // Micro Architecture
72 const Enums::DecoderFlavour _decoderFlavour;
73 const Enums::VecRegRenameMode _vecRegRenameMode;
74
75 /** Dummy device for to handle non-existing ISA devices */
76 DummyISADevice dummyDevice;
77
78 // PMU belonging to this ISA
79 BaseISADevice *pmu;
80
81 // Generic timer interface belonging to this ISA
82 std::unique_ptr<BaseISADevice> timer;
83
84 // Cached copies of system-level properties
85 bool highestELIs64;
86 bool haveSecurity;
87 bool haveLPAE;
88 bool haveVirtualization;
89 bool haveLargeAsid64;
90 uint8_t physAddrRange64;
91
92 /** Register translation entry used in lookUpMiscReg */
93 struct MiscRegLUTEntry {
94 uint32_t lower;
95 uint32_t upper;
94 uint32_t lower; // Lower half mapped to this register
95 uint32_t upper; // Upper half mapped to this register
96 };
97
96 };
97
98 struct MiscRegInitializerEntry {
99 uint32_t index;
100 struct MiscRegLUTEntry entry;
98 /** Metadata table accessible via the value of the register */
99 std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
100
101 class MiscRegLUTEntryInitializer {
102 struct MiscRegLUTEntry &entry;
103 typedef const MiscRegLUTEntryInitializer& chain;
104 public:
105 chain mapsTo(uint32_t l, uint32_t u = 0) const {
106 entry.lower = l;
107 entry.upper = u;
108 return *this;
109 }
110 MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e)
111 : entry(e)
112 {}
101 };
102
113 };
114
103 /** Register table noting all translations */
104 static const struct MiscRegInitializerEntry MiscRegSwitch[];
115 const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
116 return MiscRegLUTEntryInitializer(lookUpMiscReg[reg]);
117 }
105
118
106 /** Translation table accessible via the value of the register */
107 std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
119 void initializeMiscRegMetadata();
108
109 MiscReg miscRegs[NumMiscRegs];
110 const IntRegIndex *intRegMap;
111
112 void
113 updateRegMap(CPSR cpsr)
114 {
115 if (cpsr.width == 0) {
116 intRegMap = IntReg64Map;
117 } else {
118 switch (cpsr.mode) {
119 case MODE_USER:
120 case MODE_SYSTEM:
121 intRegMap = IntRegUsrMap;
122 break;
123 case MODE_FIQ:
124 intRegMap = IntRegFiqMap;
125 break;
126 case MODE_IRQ:
127 intRegMap = IntRegIrqMap;
128 break;
129 case MODE_SVC:
130 intRegMap = IntRegSvcMap;
131 break;
132 case MODE_MON:
133 intRegMap = IntRegMonMap;
134 break;
135 case MODE_ABORT:
136 intRegMap = IntRegAbtMap;
137 break;
138 case MODE_HYP:
139 intRegMap = IntRegHypMap;
140 break;
141 case MODE_UNDEFINED:
142 intRegMap = IntRegUndMap;
143 break;
144 default:
145 panic("Unrecognized mode setting in CPSR.\n");
146 }
147 }
148 }
149
150 BaseISADevice &getGenericTimer(ThreadContext *tc);
151
152
153 private:
154 inline void assert32(ThreadContext *tc) {
155 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
156 assert(cpsr.width);
157 }
158
159 inline void assert64(ThreadContext *tc) {
160 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
161 assert(!cpsr.width);
162 }
163
164 void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
165 bool secure_lookup, uint8_t target_el);
166
167 void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
168
169 void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
170
171 void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
172 bool hyp, uint8_t target_el);
173
174 public:
175 void clear();
176 void clear64(const ArmISAParams *p);
177
178 MiscReg readMiscRegNoEffect(int misc_reg) const;
179 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
180 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
181 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
182
183 RegId
184 flattenRegId(const RegId& regId) const
185 {
186 switch (regId.classValue()) {
187 case IntRegClass:
188 return RegId(IntRegClass, flattenIntIndex(regId.index()));
189 case FloatRegClass:
190 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
191 case VecRegClass:
192 return RegId(VecRegClass, flattenVecIndex(regId.index()));
193 case VecElemClass:
194 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
195 case CCRegClass:
196 return RegId(CCRegClass, flattenCCIndex(regId.index()));
197 case MiscRegClass:
198 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
199 }
200 return RegId();
201 }
202
203 int
204 flattenIntIndex(int reg) const
205 {
206 assert(reg >= 0);
207 if (reg < NUM_ARCH_INTREGS) {
208 return intRegMap[reg];
209 } else if (reg < NUM_INTREGS) {
210 return reg;
211 } else if (reg == INTREG_SPX) {
212 CPSR cpsr = miscRegs[MISCREG_CPSR];
213 ExceptionLevel el = opModeToEL(
214 (OperatingMode) (uint8_t) cpsr.mode);
215 if (!cpsr.sp && el != EL0)
216 return INTREG_SP0;
217 switch (el) {
218 case EL3:
219 return INTREG_SP3;
220 case EL2:
221 return INTREG_SP2;
222 case EL1:
223 return INTREG_SP1;
224 case EL0:
225 return INTREG_SP0;
226 default:
227 panic("Invalid exception level");
228 break;
229 }
230 } else {
231 return flattenIntRegModeIndex(reg);
232 }
233 }
234
235 int
236 flattenFloatIndex(int reg) const
237 {
238 assert(reg >= 0);
239 return reg;
240 }
241
242 int
243 flattenVecIndex(int reg) const
244 {
245 assert(reg >= 0);
246 return reg;
247 }
248
249 int
250 flattenVecElemIndex(int reg) const
251 {
252 assert(reg >= 0);
253 return reg;
254 }
255
256 int
257 flattenCCIndex(int reg) const
258 {
259 assert(reg >= 0);
260 return reg;
261 }
262
263 int
264 flattenMiscIndex(int reg) const
265 {
266 assert(reg >= 0);
267 int flat_idx = reg;
268
269 if (reg == MISCREG_SPSR) {
270 CPSR cpsr = miscRegs[MISCREG_CPSR];
271 switch (cpsr.mode) {
272 case MODE_EL0T:
273 warn("User mode does not have SPSR\n");
274 flat_idx = MISCREG_SPSR;
275 break;
276 case MODE_EL1T:
277 case MODE_EL1H:
278 flat_idx = MISCREG_SPSR_EL1;
279 break;
280 case MODE_EL2T:
281 case MODE_EL2H:
282 flat_idx = MISCREG_SPSR_EL2;
283 break;
284 case MODE_EL3T:
285 case MODE_EL3H:
286 flat_idx = MISCREG_SPSR_EL3;
287 break;
288 case MODE_USER:
289 warn("User mode does not have SPSR\n");
290 flat_idx = MISCREG_SPSR;
291 break;
292 case MODE_FIQ:
293 flat_idx = MISCREG_SPSR_FIQ;
294 break;
295 case MODE_IRQ:
296 flat_idx = MISCREG_SPSR_IRQ;
297 break;
298 case MODE_SVC:
299 flat_idx = MISCREG_SPSR_SVC;
300 break;
301 case MODE_MON:
302 flat_idx = MISCREG_SPSR_MON;
303 break;
304 case MODE_ABORT:
305 flat_idx = MISCREG_SPSR_ABT;
306 break;
307 case MODE_HYP:
308 flat_idx = MISCREG_SPSR_HYP;
309 break;
310 case MODE_UNDEFINED:
311 flat_idx = MISCREG_SPSR_UND;
312 break;
313 default:
314 warn("Trying to access SPSR in an invalid mode: %d\n",
315 cpsr.mode);
316 flat_idx = MISCREG_SPSR;
317 break;
318 }
319 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
320 // Mutually exclusive CP15 register
321 switch (reg) {
322 case MISCREG_PRRR_MAIR0:
323 case MISCREG_PRRR_MAIR0_NS:
324 case MISCREG_PRRR_MAIR0_S:
325 {
326 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
327 // If the muxed reg has been flattened, work out the
328 // offset and apply it to the unmuxed reg
329 int idxOffset = reg - MISCREG_PRRR_MAIR0;
330 if (ttbcr.eae)
331 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
332 idxOffset);
333 else
334 flat_idx = flattenMiscIndex(MISCREG_PRRR +
335 idxOffset);
336 }
337 break;
338 case MISCREG_NMRR_MAIR1:
339 case MISCREG_NMRR_MAIR1_NS:
340 case MISCREG_NMRR_MAIR1_S:
341 {
342 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
343 // If the muxed reg has been flattened, work out the
344 // offset and apply it to the unmuxed reg
345 int idxOffset = reg - MISCREG_NMRR_MAIR1;
346 if (ttbcr.eae)
347 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
348 idxOffset);
349 else
350 flat_idx = flattenMiscIndex(MISCREG_NMRR +
351 idxOffset);
352 }
353 break;
354 case MISCREG_PMXEVTYPER_PMCCFILTR:
355 {
356 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
357 if (pmselr.sel == 31)
358 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
359 else
360 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
361 }
362 break;
363 default:
364 panic("Unrecognized misc. register.\n");
365 break;
366 }
367 } else {
368 if (miscRegInfo[reg][MISCREG_BANKED]) {
369 bool secureReg = haveSecurity && !highestELIs64 &&
370 inSecureState(miscRegs[MISCREG_SCR],
371 miscRegs[MISCREG_CPSR]);
372 flat_idx += secureReg ? 2 : 1;
373 }
374 }
375 return flat_idx;
376 }
377
378 std::pair<int,int> getMiscIndices(int misc_reg) const
379 {
380 // Note: indexes of AArch64 registers are left unchanged
381 int flat_idx = flattenMiscIndex(misc_reg);
382
383 if (lookUpMiscReg[flat_idx].lower == 0) {
384 return std::make_pair(flat_idx, 0);
385 }
386
387 // do additional S/NS flattenings if mapped to NS while in S
388 bool S = haveSecurity && !highestELIs64 &&
389 inSecureState(miscRegs[MISCREG_SCR],
390 miscRegs[MISCREG_CPSR]);
391 int lower = lookUpMiscReg[flat_idx].lower;
392 int upper = lookUpMiscReg[flat_idx].upper;
393 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
394 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
395 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
396 return std::make_pair(lower, upper);
397 }
398
399 void serialize(CheckpointOut &cp) const
400 {
401 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
402 SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
403
404 SERIALIZE_SCALAR(highestELIs64);
405 SERIALIZE_SCALAR(haveSecurity);
406 SERIALIZE_SCALAR(haveLPAE);
407 SERIALIZE_SCALAR(haveVirtualization);
408 SERIALIZE_SCALAR(haveLargeAsid64);
409 SERIALIZE_SCALAR(physAddrRange64);
410 }
411 void unserialize(CheckpointIn &cp)
412 {
413 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
414 UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
415 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
416 updateRegMap(tmp_cpsr);
417
418 UNSERIALIZE_SCALAR(highestELIs64);
419 UNSERIALIZE_SCALAR(haveSecurity);
420 UNSERIALIZE_SCALAR(haveLPAE);
421 UNSERIALIZE_SCALAR(haveVirtualization);
422 UNSERIALIZE_SCALAR(haveLargeAsid64);
423 UNSERIALIZE_SCALAR(physAddrRange64);
424 }
425
426 void startup(ThreadContext *tc) {}
427
428 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
429
430 Enums::VecRegRenameMode
431 vecRegRenameMode() const
432 {
433 return _vecRegRenameMode;
434 }
435
436 /// Explicitly import the otherwise hidden startup
437 using SimObject::startup;
438
439 typedef ArmISAParams Params;
440
441 const Params *params() const;
442
443 ISA(Params *p);
444 };
445}
446
447template<>
448struct initRenameMode<ArmISA::ISA>
449{
450 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
451 {
452 return isa->vecRegRenameMode();
453 }
454 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
455 {
456 return mode(isa1) == mode(isa2);
457 }
458};
459
460#endif
120
121 MiscReg miscRegs[NumMiscRegs];
122 const IntRegIndex *intRegMap;
123
124 void
125 updateRegMap(CPSR cpsr)
126 {
127 if (cpsr.width == 0) {
128 intRegMap = IntReg64Map;
129 } else {
130 switch (cpsr.mode) {
131 case MODE_USER:
132 case MODE_SYSTEM:
133 intRegMap = IntRegUsrMap;
134 break;
135 case MODE_FIQ:
136 intRegMap = IntRegFiqMap;
137 break;
138 case MODE_IRQ:
139 intRegMap = IntRegIrqMap;
140 break;
141 case MODE_SVC:
142 intRegMap = IntRegSvcMap;
143 break;
144 case MODE_MON:
145 intRegMap = IntRegMonMap;
146 break;
147 case MODE_ABORT:
148 intRegMap = IntRegAbtMap;
149 break;
150 case MODE_HYP:
151 intRegMap = IntRegHypMap;
152 break;
153 case MODE_UNDEFINED:
154 intRegMap = IntRegUndMap;
155 break;
156 default:
157 panic("Unrecognized mode setting in CPSR.\n");
158 }
159 }
160 }
161
162 BaseISADevice &getGenericTimer(ThreadContext *tc);
163
164
165 private:
166 inline void assert32(ThreadContext *tc) {
167 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
168 assert(cpsr.width);
169 }
170
171 inline void assert64(ThreadContext *tc) {
172 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
173 assert(!cpsr.width);
174 }
175
176 void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
177 bool secure_lookup, uint8_t target_el);
178
179 void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
180
181 void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
182
183 void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
184 bool hyp, uint8_t target_el);
185
186 public:
187 void clear();
188 void clear64(const ArmISAParams *p);
189
190 MiscReg readMiscRegNoEffect(int misc_reg) const;
191 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
192 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
193 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
194
195 RegId
196 flattenRegId(const RegId& regId) const
197 {
198 switch (regId.classValue()) {
199 case IntRegClass:
200 return RegId(IntRegClass, flattenIntIndex(regId.index()));
201 case FloatRegClass:
202 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
203 case VecRegClass:
204 return RegId(VecRegClass, flattenVecIndex(regId.index()));
205 case VecElemClass:
206 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
207 case CCRegClass:
208 return RegId(CCRegClass, flattenCCIndex(regId.index()));
209 case MiscRegClass:
210 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
211 }
212 return RegId();
213 }
214
215 int
216 flattenIntIndex(int reg) const
217 {
218 assert(reg >= 0);
219 if (reg < NUM_ARCH_INTREGS) {
220 return intRegMap[reg];
221 } else if (reg < NUM_INTREGS) {
222 return reg;
223 } else if (reg == INTREG_SPX) {
224 CPSR cpsr = miscRegs[MISCREG_CPSR];
225 ExceptionLevel el = opModeToEL(
226 (OperatingMode) (uint8_t) cpsr.mode);
227 if (!cpsr.sp && el != EL0)
228 return INTREG_SP0;
229 switch (el) {
230 case EL3:
231 return INTREG_SP3;
232 case EL2:
233 return INTREG_SP2;
234 case EL1:
235 return INTREG_SP1;
236 case EL0:
237 return INTREG_SP0;
238 default:
239 panic("Invalid exception level");
240 break;
241 }
242 } else {
243 return flattenIntRegModeIndex(reg);
244 }
245 }
246
247 int
248 flattenFloatIndex(int reg) const
249 {
250 assert(reg >= 0);
251 return reg;
252 }
253
254 int
255 flattenVecIndex(int reg) const
256 {
257 assert(reg >= 0);
258 return reg;
259 }
260
261 int
262 flattenVecElemIndex(int reg) const
263 {
264 assert(reg >= 0);
265 return reg;
266 }
267
268 int
269 flattenCCIndex(int reg) const
270 {
271 assert(reg >= 0);
272 return reg;
273 }
274
275 int
276 flattenMiscIndex(int reg) const
277 {
278 assert(reg >= 0);
279 int flat_idx = reg;
280
281 if (reg == MISCREG_SPSR) {
282 CPSR cpsr = miscRegs[MISCREG_CPSR];
283 switch (cpsr.mode) {
284 case MODE_EL0T:
285 warn("User mode does not have SPSR\n");
286 flat_idx = MISCREG_SPSR;
287 break;
288 case MODE_EL1T:
289 case MODE_EL1H:
290 flat_idx = MISCREG_SPSR_EL1;
291 break;
292 case MODE_EL2T:
293 case MODE_EL2H:
294 flat_idx = MISCREG_SPSR_EL2;
295 break;
296 case MODE_EL3T:
297 case MODE_EL3H:
298 flat_idx = MISCREG_SPSR_EL3;
299 break;
300 case MODE_USER:
301 warn("User mode does not have SPSR\n");
302 flat_idx = MISCREG_SPSR;
303 break;
304 case MODE_FIQ:
305 flat_idx = MISCREG_SPSR_FIQ;
306 break;
307 case MODE_IRQ:
308 flat_idx = MISCREG_SPSR_IRQ;
309 break;
310 case MODE_SVC:
311 flat_idx = MISCREG_SPSR_SVC;
312 break;
313 case MODE_MON:
314 flat_idx = MISCREG_SPSR_MON;
315 break;
316 case MODE_ABORT:
317 flat_idx = MISCREG_SPSR_ABT;
318 break;
319 case MODE_HYP:
320 flat_idx = MISCREG_SPSR_HYP;
321 break;
322 case MODE_UNDEFINED:
323 flat_idx = MISCREG_SPSR_UND;
324 break;
325 default:
326 warn("Trying to access SPSR in an invalid mode: %d\n",
327 cpsr.mode);
328 flat_idx = MISCREG_SPSR;
329 break;
330 }
331 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
332 // Mutually exclusive CP15 register
333 switch (reg) {
334 case MISCREG_PRRR_MAIR0:
335 case MISCREG_PRRR_MAIR0_NS:
336 case MISCREG_PRRR_MAIR0_S:
337 {
338 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
339 // If the muxed reg has been flattened, work out the
340 // offset and apply it to the unmuxed reg
341 int idxOffset = reg - MISCREG_PRRR_MAIR0;
342 if (ttbcr.eae)
343 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
344 idxOffset);
345 else
346 flat_idx = flattenMiscIndex(MISCREG_PRRR +
347 idxOffset);
348 }
349 break;
350 case MISCREG_NMRR_MAIR1:
351 case MISCREG_NMRR_MAIR1_NS:
352 case MISCREG_NMRR_MAIR1_S:
353 {
354 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
355 // If the muxed reg has been flattened, work out the
356 // offset and apply it to the unmuxed reg
357 int idxOffset = reg - MISCREG_NMRR_MAIR1;
358 if (ttbcr.eae)
359 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
360 idxOffset);
361 else
362 flat_idx = flattenMiscIndex(MISCREG_NMRR +
363 idxOffset);
364 }
365 break;
366 case MISCREG_PMXEVTYPER_PMCCFILTR:
367 {
368 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
369 if (pmselr.sel == 31)
370 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
371 else
372 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
373 }
374 break;
375 default:
376 panic("Unrecognized misc. register.\n");
377 break;
378 }
379 } else {
380 if (miscRegInfo[reg][MISCREG_BANKED]) {
381 bool secureReg = haveSecurity && !highestELIs64 &&
382 inSecureState(miscRegs[MISCREG_SCR],
383 miscRegs[MISCREG_CPSR]);
384 flat_idx += secureReg ? 2 : 1;
385 }
386 }
387 return flat_idx;
388 }
389
390 std::pair<int,int> getMiscIndices(int misc_reg) const
391 {
392 // Note: indexes of AArch64 registers are left unchanged
393 int flat_idx = flattenMiscIndex(misc_reg);
394
395 if (lookUpMiscReg[flat_idx].lower == 0) {
396 return std::make_pair(flat_idx, 0);
397 }
398
399 // do additional S/NS flattenings if mapped to NS while in S
400 bool S = haveSecurity && !highestELIs64 &&
401 inSecureState(miscRegs[MISCREG_SCR],
402 miscRegs[MISCREG_CPSR]);
403 int lower = lookUpMiscReg[flat_idx].lower;
404 int upper = lookUpMiscReg[flat_idx].upper;
405 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
406 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
407 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
408 return std::make_pair(lower, upper);
409 }
410
411 void serialize(CheckpointOut &cp) const
412 {
413 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
414 SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
415
416 SERIALIZE_SCALAR(highestELIs64);
417 SERIALIZE_SCALAR(haveSecurity);
418 SERIALIZE_SCALAR(haveLPAE);
419 SERIALIZE_SCALAR(haveVirtualization);
420 SERIALIZE_SCALAR(haveLargeAsid64);
421 SERIALIZE_SCALAR(physAddrRange64);
422 }
423 void unserialize(CheckpointIn &cp)
424 {
425 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
426 UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
427 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
428 updateRegMap(tmp_cpsr);
429
430 UNSERIALIZE_SCALAR(highestELIs64);
431 UNSERIALIZE_SCALAR(haveSecurity);
432 UNSERIALIZE_SCALAR(haveLPAE);
433 UNSERIALIZE_SCALAR(haveVirtualization);
434 UNSERIALIZE_SCALAR(haveLargeAsid64);
435 UNSERIALIZE_SCALAR(physAddrRange64);
436 }
437
438 void startup(ThreadContext *tc) {}
439
440 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
441
442 Enums::VecRegRenameMode
443 vecRegRenameMode() const
444 {
445 return _vecRegRenameMode;
446 }
447
448 /// Explicitly import the otherwise hidden startup
449 using SimObject::startup;
450
451 typedef ArmISAParams Params;
452
453 const Params *params() const;
454
455 ISA(Params *p);
456 };
457}
458
459template<>
460struct initRenameMode<ArmISA::ISA>
461{
462 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
463 {
464 return isa->vecRegRenameMode();
465 }
466 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
467 {
468 return mode(isa1) == mode(isa2);
469 }
470};
471
472#endif