3ee0d618fc91f5c2a03d072f6edd90f5c2889e5c
[gem5.git] / src / arch / arm / isa / insts / misc.isa
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2010-2013,2017-2020 ARM Limited
4 // All rights reserved
5 //
6 // The license below extends only to copyright in the software and shall
7 // not be construed as granting a license to any other intellectual
8 // property including but not limited to intellectual property relating
9 // to a hardware implementation of the functionality of the software
10 // licensed hereunder. You may use the software subject to the license
11 // terms below provided that you ensure that this notice is replicated
12 // unmodified and in its entirety in all distributions of the software,
13 // modified or unmodified, in source code or in binary form.
14 //
15 // Redistribution and use in source and binary forms, with or without
16 // modification, are permitted provided that the following conditions are
17 // met: redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer;
19 // redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution;
22 // neither the name of the copyright holders nor the names of its
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
38 let {{
39
40 svcCode = '''
41 ThreadContext *tc = xc->tcBase();
42
43 bool have_semi = ArmSystem::haveSemihosting(tc);
44 if (have_semi && Thumb && imm == ArmSemihosting::T32Imm) {
45 // Enable gem5 extensions since we can't distinguish in thumb.
46 ArmSystem::callSemihosting32(tc, true);
47 } else if (have_semi && imm == ArmSemihosting::A32Imm) {
48 ArmSystem::callSemihosting32(tc);
49 } else if (have_semi && imm == ArmSemihosting::Gem5Imm) {
50 ArmSystem::callSemihosting32(tc, true);
51 } else {
52 fault = std::make_shared<SupervisorCall>(machInst, imm);
53 }
54 '''
55
56 svcIop = InstObjParams("svc", "Svc", "ImmOp",
57 { "code": svcCode,
58 "predicate_test": predicateTest,
59 "thumb_semihost": '0xAB',
60 "arm_semihost": '0x123456' },
61 ["IsSyscall", "IsNonSpeculative",
62 "IsSerializeAfter"])
63 header_output = ImmOpDeclare.subst(svcIop)
64 decoder_output = SemihostConstructor.subst(svcIop)
65 exec_output = PredOpExecute.subst(svcIop)
66
67 hltCode = '''
68 ThreadContext *tc = xc->tcBase();
69
70 const auto semihost_imm = Thumb? 0x3C : 0xF000;
71
72 if (ArmSystem::haveSemihosting(tc) && imm == semihost_imm) {
73 ArmSystem::callSemihosting32(tc);
74 } else {
75 // HLT instructions aren't implemented, so treat them as undefined
76 // instructions.
77 fault = std::make_shared<UndefinedInstruction>(
78 machInst, false, mnemonic);
79 }
80 '''
81
82 hltIop = InstObjParams("hlt", "Hlt", "ImmOp",
83 { "code": hltCode,
84 "predicate_test": predicateTest,
85 "thumb_semihost": '0x3C',
86 "arm_semihost": '0xF000' },
87 ["IsNonSpeculative", "IsSerializeAfter"])
88 header_output += ImmOpDeclare.subst(hltIop)
89 decoder_output += SemihostConstructor.subst(hltIop)
90 exec_output += PredOpExecute.subst(hltIop)
91
92 smcCode = '''
93 HCR hcr = Hcr;
94 CPSR cpsr = Cpsr;
95 SCR scr = Scr;
96
97 if ((cpsr.mode != MODE_USER) && FullSystem) {
98 if (EL2Enabled(xc->tcBase()) && (cpsr.mode != MODE_HYP) && hcr.tsc) {
99 fault = std::make_shared<HypervisorTrap>(machInst, 0,
100 EC_SMC_TO_HYP);
101 } else {
102 if (scr.scd) {
103 fault = disabledFault();
104 } else {
105 fault = std::make_shared<SecureMonitorCall>(machInst);
106 }
107 }
108 } else {
109 fault = disabledFault();
110 }
111 '''
112
113 smcIop = InstObjParams("smc", "Smc", "PredOp",
114 { "code": smcCode,
115 "predicate_test": predicateTest },
116 ["IsNonSpeculative", "IsSerializeAfter"])
117 header_output += BasicDeclare.subst(smcIop)
118 decoder_output += BasicConstructor.subst(smcIop)
119 exec_output += PredOpExecute.subst(smcIop)
120
121 hvcCode = '''
122 CPSR cpsr = Cpsr;
123
124 // Filter out the various cases where this instruction isn't defined
125 if (!FullSystem || !ArmSystem::haveVirtualization(xc->tcBase()) ||
126 (cpsr.mode == MODE_USER) ||
127 (isSecure(xc->tcBase()) && !IsSecureEL2Enabled(xc->tcBase()))) {
128 fault = disabledFault();
129 } else {
130 fault = std::make_shared<HypervisorCall>(machInst, imm);
131 }
132 '''
133
134 hvcIop = InstObjParams("hvc", "Hvc", "ImmOp",
135 { "code": hvcCode,
136 "predicate_test": predicateTest },
137 ["IsNonSpeculative", "IsSerializeAfter"])
138 header_output += ImmOpDeclare.subst(hvcIop)
139 decoder_output += ImmOpConstructor.subst(hvcIop)
140 exec_output += PredOpExecute.subst(hvcIop)
141
142 eretCode = '''
143 SCTLR sctlr = Sctlr;
144 CPSR old_cpsr = Cpsr;
145 old_cpsr.nz = CondCodesNZ;
146 old_cpsr.c = CondCodesC;
147 old_cpsr.v = CondCodesV;
148 old_cpsr.ge = CondCodesGE;
149
150 CPSR new_cpsr = cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF,
151 true, sctlr.nmfi, xc->tcBase());
152 Cpsr = ~CondCodesMask & new_cpsr;
153 CondCodesNZ = new_cpsr.nz;
154 CondCodesC = new_cpsr.c;
155 CondCodesV = new_cpsr.v;
156 CondCodesGE = new_cpsr.ge;
157
158 NextThumb = (new_cpsr).t;
159 NextJazelle = (new_cpsr).j;
160 NextItState = (((new_cpsr).it2 << 2) & 0xFC)
161 | ((new_cpsr).it1 & 0x3);
162
163 NPC = (old_cpsr.mode == MODE_HYP) ? ElrHyp : LR;
164 '''
165
166 eretIop = InstObjParams("eret", "Eret", "PredOp",
167 { "code": eretCode,
168 "predicate_test": predicateTest },
169 ["IsNonSpeculative", "IsSerializeAfter",
170 "IsSquashAfter"])
171 header_output += BasicDeclare.subst(eretIop)
172 decoder_output += BasicConstructor.subst(eretIop)
173 exec_output += PredOpExecute.subst(eretIop)
174
175 crcCode = '''
176 constexpr uint8_t size_bytes = %(sz)d;
177 constexpr uint32_t poly = %(polynom)s;
178
179 uint32_t data = htole(Op2);
180 auto data_buffer = reinterpret_cast<uint8_t*>(&data);
181
182 Dest = crc32<poly>(
183 data_buffer, /* Message Register */
184 Op1, /* Initial Value of the CRC */
185 size_bytes /* Size of the original Message */
186 );
187 '''
188
189 def crc32Emit(mnem, implCode, castagnoli, size):
190 global header_output, decoder_output, exec_output
191
192 if castagnoli:
193 # crc32c instructions
194 poly = "0x1EDC6F41"
195 else:
196 # crc32 instructions
197 poly = "0x04C11DB7"
198
199 data = {'sz' : size, 'polynom': poly}
200
201 instCode = implCode % data
202
203 crcIop = InstObjParams(mnem, mnem.capitalize(), "RegRegRegOp",
204 { "code": instCode,
205 "predicate_test": predicateTest }, [])
206 header_output += RegRegRegOpDeclare.subst(crcIop)
207 decoder_output += RegRegRegOpConstructor.subst(crcIop)
208 exec_output += PredOpExecute.subst(crcIop)
209
210 crc32Emit("crc32b", crcCode, False, 1);
211 crc32Emit("crc32h", crcCode, False, 2);
212 crc32Emit("crc32w", crcCode, False, 4);
213 crc32Emit("crc32cb", crcCode, True, 1);
214 crc32Emit("crc32ch", crcCode, True, 2);
215 crc32Emit("crc32cw", crcCode, True, 4);
216
217 }};
218
219 let {{
220
221 header_output = decoder_output = exec_output = ""
222
223 mrsCpsrCode = '''
224 CPSR cpsr = Cpsr;
225 cpsr.nz = CondCodesNZ;
226 cpsr.c = CondCodesC;
227 cpsr.v = CondCodesV;
228 cpsr.ge = CondCodesGE;
229 Dest = cpsr & (cpsr.mode == MODE_USER ? ApsrMask : CpsrMask);
230 '''
231
232 mrsCpsrIop = InstObjParams("mrs", "MrsCpsr", "MrsOp",
233 { "code": mrsCpsrCode,
234 "predicate_test": condPredicateTest },
235 ["IsSerializeBefore"])
236 header_output += MrsDeclare.subst(mrsCpsrIop)
237 decoder_output += MrsConstructor.subst(mrsCpsrIop)
238 exec_output += PredOpExecute.subst(mrsCpsrIop)
239
240 mrsSpsrCode = "Dest = Spsr"
241 mrsSpsrIop = InstObjParams("mrs", "MrsSpsr", "MrsOp",
242 { "code": mrsSpsrCode,
243 "predicate_test": predicateTest },
244 ["IsSerializeBefore"])
245 header_output += MrsDeclare.subst(mrsSpsrIop)
246 decoder_output += MrsConstructor.subst(mrsSpsrIop)
247 exec_output += PredOpExecute.subst(mrsSpsrIop)
248
249 mrsBankedRegCode = '''
250 bool isIntReg;
251 int regIdx;
252
253 if (decodeMrsMsrBankedReg(byteMask, r, isIntReg, regIdx, Cpsr, Scr, Nsacr)) {
254 if (isIntReg) {
255 Dest = DecodedBankedIntReg;
256 } else {
257 Dest = xc->readMiscReg(regIdx);
258 }
259 } else {
260 return std::make_shared<UndefinedInstruction>(machInst, false,
261 mnemonic);
262 }
263 '''
264 mrsBankedRegIop = InstObjParams("mrs", "MrsBankedReg", "MrsOp",
265 { "code": mrsBankedRegCode,
266 "predicate_test": predicateTest },
267 ["IsSerializeBefore"])
268 header_output += MrsBankedRegDeclare.subst(mrsBankedRegIop)
269 decoder_output += MrsBankedRegConstructor.subst(mrsBankedRegIop)
270 exec_output += PredOpExecute.subst(mrsBankedRegIop)
271
272 msrBankedRegCode = '''
273 bool isIntReg;
274 int regIdx;
275
276 if (decodeMrsMsrBankedReg(byteMask, r, isIntReg, regIdx, Cpsr, Scr, Nsacr)) {
277 if (isIntReg) {
278 // This is a bit nasty, you would have thought that
279 // DecodedBankedIntReg wouldn't be written to unless the
280 // conditions on the IF statements above are met, however if
281 // you look at the generated C code you'll find that they are.
282 // However this is safe as DecodedBankedIntReg (which is used
283 // in operands.isa to get the index of DecodedBankedIntReg)
284 // will return INTREG_DUMMY if its not a valid integer
285 // register, so redirecting the write to somewhere we don't
286 // care about.
287 DecodedBankedIntReg = Op1;
288 } else {
289 xc->setMiscReg(regIdx, Op1);
290 }
291 } else {
292 return std::make_shared<UndefinedInstruction>(machInst, false,
293 mnemonic);
294 }
295 '''
296 msrBankedRegIop = InstObjParams("msr", "MsrBankedReg", "MsrRegOp",
297 { "code": msrBankedRegCode,
298 "predicate_test": predicateTest },
299 ["IsSerializeAfter", "IsNonSpeculative"])
300 header_output += MsrBankedRegDeclare.subst(msrBankedRegIop)
301 decoder_output += MsrBankedRegConstructor.subst(msrBankedRegIop)
302 exec_output += PredOpExecute.subst(msrBankedRegIop)
303
304 msrCpsrRegCode = '''
305 SCTLR sctlr = Sctlr;
306 CPSR old_cpsr = Cpsr;
307 old_cpsr.nz = CondCodesNZ;
308 old_cpsr.c = CondCodesC;
309 old_cpsr.v = CondCodesV;
310 old_cpsr.ge = CondCodesGE;
311
312 CPSR new_cpsr =
313 cpsrWriteByInstr(old_cpsr, Op1, Scr, Nsacr, byteMask, false,
314 sctlr.nmfi, xc->tcBase());
315 Cpsr = ~CondCodesMask & new_cpsr;
316 CondCodesNZ = new_cpsr.nz;
317 CondCodesC = new_cpsr.c;
318 CondCodesV = new_cpsr.v;
319 CondCodesGE = new_cpsr.ge;
320 '''
321 msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp",
322 { "code": msrCpsrRegCode,
323 "predicate_test": condPredicateTest },
324 ["IsSerializeAfter","IsNonSpeculative"])
325 header_output += MsrRegDeclare.subst(msrCpsrRegIop)
326 decoder_output += MsrRegConstructor.subst(msrCpsrRegIop)
327 exec_output += PredOpExecute.subst(msrCpsrRegIop)
328
329 msrSpsrRegCode = "Spsr = spsrWriteByInstr(Spsr, Op1, byteMask, false);"
330 msrSpsrRegIop = InstObjParams("msr", "MsrSpsrReg", "MsrRegOp",
331 { "code": msrSpsrRegCode,
332 "predicate_test": predicateTest },
333 ["IsSerializeAfter","IsNonSpeculative"])
334 header_output += MsrRegDeclare.subst(msrSpsrRegIop)
335 decoder_output += MsrRegConstructor.subst(msrSpsrRegIop)
336 exec_output += PredOpExecute.subst(msrSpsrRegIop)
337
338 msrCpsrImmCode = '''
339 SCTLR sctlr = Sctlr;
340 CPSR old_cpsr = Cpsr;
341 old_cpsr.nz = CondCodesNZ;
342 old_cpsr.c = CondCodesC;
343 old_cpsr.v = CondCodesV;
344 old_cpsr.ge = CondCodesGE;
345 CPSR new_cpsr =
346 cpsrWriteByInstr(old_cpsr, imm, Scr, Nsacr, byteMask, false,
347 sctlr.nmfi, xc->tcBase());
348 Cpsr = ~CondCodesMask & new_cpsr;
349 CondCodesNZ = new_cpsr.nz;
350 CondCodesC = new_cpsr.c;
351 CondCodesV = new_cpsr.v;
352 CondCodesGE = new_cpsr.ge;
353 '''
354 msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp",
355 { "code": msrCpsrImmCode,
356 "predicate_test": condPredicateTest },
357 ["IsSerializeAfter","IsNonSpeculative"])
358 header_output += MsrImmDeclare.subst(msrCpsrImmIop)
359 decoder_output += MsrImmConstructor.subst(msrCpsrImmIop)
360 exec_output += PredOpExecute.subst(msrCpsrImmIop)
361
362 msrSpsrImmCode = "Spsr = spsrWriteByInstr(Spsr, imm, byteMask, false);"
363 msrSpsrImmIop = InstObjParams("msr", "MsrSpsrImm", "MsrImmOp",
364 { "code": msrSpsrImmCode,
365 "predicate_test": predicateTest },
366 ["IsSerializeAfter","IsNonSpeculative"])
367 header_output += MsrImmDeclare.subst(msrSpsrImmIop)
368 decoder_output += MsrImmConstructor.subst(msrSpsrImmIop)
369 exec_output += PredOpExecute.subst(msrSpsrImmIop)
370
371 revCode = '''
372 uint32_t val = Op1;
373 Dest = swap_byte(val);
374 '''
375 revIop = InstObjParams("rev", "Rev", "RegRegOp",
376 { "code": revCode,
377 "predicate_test": predicateTest }, [])
378 header_output += RegRegOpDeclare.subst(revIop)
379 decoder_output += RegRegOpConstructor.subst(revIop)
380 exec_output += PredOpExecute.subst(revIop)
381
382 rev16Code = '''
383 uint32_t val = Op1;
384 Dest = (bits(val, 15, 8) << 0) |
385 (bits(val, 7, 0) << 8) |
386 (bits(val, 31, 24) << 16) |
387 (bits(val, 23, 16) << 24);
388 '''
389 rev16Iop = InstObjParams("rev16", "Rev16", "RegRegOp",
390 { "code": rev16Code,
391 "predicate_test": predicateTest }, [])
392 header_output += RegRegOpDeclare.subst(rev16Iop)
393 decoder_output += RegRegOpConstructor.subst(rev16Iop)
394 exec_output += PredOpExecute.subst(rev16Iop)
395
396 revshCode = '''
397 uint16_t val = Op1;
398 Dest = sext<16>(swap_byte(val));
399 '''
400 revshIop = InstObjParams("revsh", "Revsh", "RegRegOp",
401 { "code": revshCode,
402 "predicate_test": predicateTest }, [])
403 header_output += RegRegOpDeclare.subst(revshIop)
404 decoder_output += RegRegOpConstructor.subst(revshIop)
405 exec_output += PredOpExecute.subst(revshIop)
406
407 rbitCode = '''
408 Dest = reverseBits(Op1);
409 '''
410 rbitIop = InstObjParams("rbit", "Rbit", "RegRegOp",
411 { "code": rbitCode,
412 "predicate_test": predicateTest }, [])
413 header_output += RegRegOpDeclare.subst(rbitIop)
414 decoder_output += RegRegOpConstructor.subst(rbitIop)
415 exec_output += PredOpExecute.subst(rbitIop)
416
417 clzCode = '''
418 Dest = (Op1 == 0) ? 32 : (31 - findMsbSet(Op1));
419 '''
420 clzIop = InstObjParams("clz", "Clz", "RegRegOp",
421 { "code": clzCode,
422 "predicate_test": predicateTest }, [])
423 header_output += RegRegOpDeclare.subst(clzIop)
424 decoder_output += RegRegOpConstructor.subst(clzIop)
425 exec_output += PredOpExecute.subst(clzIop)
426
427 ssatCode = '''
428 int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0);
429 int32_t res;
430 if (satInt(res, operand, imm))
431 CpsrQ = 1 << 27;
432 Dest = res;
433 '''
434 ssatIop = InstObjParams("ssat", "Ssat", "RegImmRegShiftOp",
435 { "code": ssatCode,
436 "predicate_test": pickPredicate(ssatCode) }, [])
437 header_output += RegImmRegShiftOpDeclare.subst(ssatIop)
438 decoder_output += RegImmRegShiftOpConstructor.subst(ssatIop)
439 exec_output += PredOpExecute.subst(ssatIop)
440
441 usatCode = '''
442 int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0);
443 int32_t res;
444 if (uSatInt(res, operand, imm))
445 CpsrQ = 1 << 27;
446 Dest = res;
447 '''
448 usatIop = InstObjParams("usat", "Usat", "RegImmRegShiftOp",
449 { "code": usatCode,
450 "predicate_test": pickPredicate(usatCode) }, [])
451 header_output += RegImmRegShiftOpDeclare.subst(usatIop)
452 decoder_output += RegImmRegShiftOpConstructor.subst(usatIop)
453 exec_output += PredOpExecute.subst(usatIop)
454
455 ssat16Code = '''
456 int32_t res;
457 uint32_t resTemp = 0;
458 int32_t argLow = sext<16>(bits(Op1, 15, 0));
459 int32_t argHigh = sext<16>(bits(Op1, 31, 16));
460 if (satInt(res, argLow, imm))
461 CpsrQ = 1 << 27;
462 replaceBits(resTemp, 15, 0, res);
463 if (satInt(res, argHigh, imm))
464 CpsrQ = 1 << 27;
465 replaceBits(resTemp, 31, 16, res);
466 Dest = resTemp;
467 '''
468 ssat16Iop = InstObjParams("ssat16", "Ssat16", "RegImmRegOp",
469 { "code": ssat16Code,
470 "predicate_test": pickPredicate(ssat16Code) }, [])
471 header_output += RegImmRegOpDeclare.subst(ssat16Iop)
472 decoder_output += RegImmRegOpConstructor.subst(ssat16Iop)
473 exec_output += PredOpExecute.subst(ssat16Iop)
474
475 usat16Code = '''
476 int32_t res;
477 uint32_t resTemp = 0;
478 int32_t argLow = sext<16>(bits(Op1, 15, 0));
479 int32_t argHigh = sext<16>(bits(Op1, 31, 16));
480 if (uSatInt(res, argLow, imm))
481 CpsrQ = 1 << 27;
482 replaceBits(resTemp, 15, 0, res);
483 if (uSatInt(res, argHigh, imm))
484 CpsrQ = 1 << 27;
485 replaceBits(resTemp, 31, 16, res);
486 Dest = resTemp;
487 '''
488 usat16Iop = InstObjParams("usat16", "Usat16", "RegImmRegOp",
489 { "code": usat16Code,
490 "predicate_test": pickPredicate(usat16Code) }, [])
491 header_output += RegImmRegOpDeclare.subst(usat16Iop)
492 decoder_output += RegImmRegOpConstructor.subst(usat16Iop)
493 exec_output += PredOpExecute.subst(usat16Iop)
494
495 sxtbIop = InstObjParams("sxtb", "Sxtb", "RegImmRegOp",
496 { "code":
497 "Dest = sext<8>((uint8_t)(Op1_ud >> imm));",
498 "predicate_test": predicateTest }, [])
499 header_output += RegImmRegOpDeclare.subst(sxtbIop)
500 decoder_output += RegImmRegOpConstructor.subst(sxtbIop)
501 exec_output += PredOpExecute.subst(sxtbIop)
502
503 sxtabIop = InstObjParams("sxtab", "Sxtab", "RegRegRegImmOp",
504 { "code":
505 '''
506 Dest = sext<8>((uint8_t)(Op2_ud >> imm)) +
507 Op1;
508 ''',
509 "predicate_test": predicateTest }, [])
510 header_output += RegRegRegImmOpDeclare.subst(sxtabIop)
511 decoder_output += RegRegRegImmOpConstructor.subst(sxtabIop)
512 exec_output += PredOpExecute.subst(sxtabIop)
513
514 sxtb16Code = '''
515 uint32_t resTemp = 0;
516 replaceBits(resTemp, 15, 0, sext<8>(bits(Op1, imm + 7, imm)));
517 replaceBits(resTemp, 31, 16,
518 sext<8>(bits(Op1, (imm + 23) % 32, (imm + 16) % 32)));
519 Dest = resTemp;
520 '''
521 sxtb16Iop = InstObjParams("sxtb16", "Sxtb16", "RegImmRegOp",
522 { "code": sxtb16Code,
523 "predicate_test": predicateTest }, [])
524 header_output += RegImmRegOpDeclare.subst(sxtb16Iop)
525 decoder_output += RegImmRegOpConstructor.subst(sxtb16Iop)
526 exec_output += PredOpExecute.subst(sxtb16Iop)
527
528 sxtab16Code = '''
529 uint32_t resTemp = 0;
530 replaceBits(resTemp, 15, 0, sext<8>(bits(Op2, imm + 7, imm)) +
531 bits(Op1, 15, 0));
532 replaceBits(resTemp, 31, 16,
533 sext<8>(bits(Op2, (imm + 23) % 32, (imm + 16) % 32)) +
534 bits(Op1, 31, 16));
535 Dest = resTemp;
536 '''
537 sxtab16Iop = InstObjParams("sxtab16", "Sxtab16", "RegRegRegImmOp",
538 { "code": sxtab16Code,
539 "predicate_test": predicateTest }, [])
540 header_output += RegRegRegImmOpDeclare.subst(sxtab16Iop)
541 decoder_output += RegRegRegImmOpConstructor.subst(sxtab16Iop)
542 exec_output += PredOpExecute.subst(sxtab16Iop)
543
544 sxthCode = '''
545 uint64_t rotated = (uint32_t)Op1;
546 rotated = (rotated | (rotated << 32)) >> imm;
547 Dest = sext<16>((uint16_t)rotated);
548 '''
549 sxthIop = InstObjParams("sxth", "Sxth", "RegImmRegOp",
550 { "code": sxthCode,
551 "predicate_test": predicateTest }, [])
552 header_output += RegImmRegOpDeclare.subst(sxthIop)
553 decoder_output += RegImmRegOpConstructor.subst(sxthIop)
554 exec_output += PredOpExecute.subst(sxthIop)
555
556 sxtahCode = '''
557 uint64_t rotated = (uint32_t)Op2;
558 rotated = (rotated | (rotated << 32)) >> imm;
559 Dest = sext<16>((uint16_t)rotated) + Op1;
560 '''
561 sxtahIop = InstObjParams("sxtah", "Sxtah", "RegRegRegImmOp",
562 { "code": sxtahCode,
563 "predicate_test": predicateTest }, [])
564 header_output += RegRegRegImmOpDeclare.subst(sxtahIop)
565 decoder_output += RegRegRegImmOpConstructor.subst(sxtahIop)
566 exec_output += PredOpExecute.subst(sxtahIop)
567
568 uxtbIop = InstObjParams("uxtb", "Uxtb", "RegImmRegOp",
569 { "code": "Dest = (uint8_t)(Op1_ud >> imm);",
570 "predicate_test": predicateTest }, [])
571 header_output += RegImmRegOpDeclare.subst(uxtbIop)
572 decoder_output += RegImmRegOpConstructor.subst(uxtbIop)
573 exec_output += PredOpExecute.subst(uxtbIop)
574
575 uxtabIop = InstObjParams("uxtab", "Uxtab", "RegRegRegImmOp",
576 { "code":
577 "Dest = (uint8_t)(Op2_ud >> imm) + Op1;",
578 "predicate_test": predicateTest }, [])
579 header_output += RegRegRegImmOpDeclare.subst(uxtabIop)
580 decoder_output += RegRegRegImmOpConstructor.subst(uxtabIop)
581 exec_output += PredOpExecute.subst(uxtabIop)
582
583 uxtb16Code = '''
584 uint32_t resTemp = 0;
585 replaceBits(resTemp, 15, 0, (uint8_t)(bits(Op1, imm + 7, imm)));
586 replaceBits(resTemp, 31, 16,
587 (uint8_t)(bits(Op1, (imm + 23) % 32, (imm + 16) % 32)));
588 Dest = resTemp;
589 '''
590 uxtb16Iop = InstObjParams("uxtb16", "Uxtb16", "RegImmRegOp",
591 { "code": uxtb16Code,
592 "predicate_test": predicateTest }, [])
593 header_output += RegImmRegOpDeclare.subst(uxtb16Iop)
594 decoder_output += RegImmRegOpConstructor.subst(uxtb16Iop)
595 exec_output += PredOpExecute.subst(uxtb16Iop)
596
597 uxtab16Code = '''
598 uint32_t resTemp = 0;
599 replaceBits(resTemp, 15, 0, (uint8_t)(bits(Op2, imm + 7, imm)) +
600 bits(Op1, 15, 0));
601 replaceBits(resTemp, 31, 16,
602 (uint8_t)(bits(Op2, (imm + 23) % 32, (imm + 16) % 32)) +
603 bits(Op1, 31, 16));
604 Dest = resTemp;
605 '''
606 uxtab16Iop = InstObjParams("uxtab16", "Uxtab16", "RegRegRegImmOp",
607 { "code": uxtab16Code,
608 "predicate_test": predicateTest }, [])
609 header_output += RegRegRegImmOpDeclare.subst(uxtab16Iop)
610 decoder_output += RegRegRegImmOpConstructor.subst(uxtab16Iop)
611 exec_output += PredOpExecute.subst(uxtab16Iop)
612
613 uxthCode = '''
614 uint64_t rotated = (uint32_t)Op1;
615 rotated = (rotated | (rotated << 32)) >> imm;
616 Dest = (uint16_t)rotated;
617 '''
618 uxthIop = InstObjParams("uxth", "Uxth", "RegImmRegOp",
619 { "code": uxthCode,
620 "predicate_test": predicateTest }, [])
621 header_output += RegImmRegOpDeclare.subst(uxthIop)
622 decoder_output += RegImmRegOpConstructor.subst(uxthIop)
623 exec_output += PredOpExecute.subst(uxthIop)
624
625 uxtahCode = '''
626 uint64_t rotated = (uint32_t)Op2;
627 rotated = (rotated | (rotated << 32)) >> imm;
628 Dest = (uint16_t)rotated + Op1;
629 '''
630 uxtahIop = InstObjParams("uxtah", "Uxtah", "RegRegRegImmOp",
631 { "code": uxtahCode,
632 "predicate_test": predicateTest }, [])
633 header_output += RegRegRegImmOpDeclare.subst(uxtahIop)
634 decoder_output += RegRegRegImmOpConstructor.subst(uxtahIop)
635 exec_output += PredOpExecute.subst(uxtahIop)
636
637 selCode = '''
638 uint32_t resTemp = 0;
639 for (unsigned i = 0; i < 4; i++) {
640 int low = i * 8;
641 int high = low + 7;
642 replaceBits(resTemp, high, low,
643 bits(CondCodesGE, i) ?
644 bits(Op1, high, low) : bits(Op2, high, low));
645 }
646 Dest = resTemp;
647 '''
648 selIop = InstObjParams("sel", "Sel", "RegRegRegOp",
649 { "code": selCode,
650 "predicate_test": predicateTest }, [])
651 header_output += RegRegRegOpDeclare.subst(selIop)
652 decoder_output += RegRegRegOpConstructor.subst(selIop)
653 exec_output += PredOpExecute.subst(selIop)
654
655 usad8Code = '''
656 uint32_t resTemp = 0;
657 for (unsigned i = 0; i < 4; i++) {
658 int low = i * 8;
659 int high = low + 7;
660 int32_t diff = bits(Op1, high, low) -
661 bits(Op2, high, low);
662 resTemp += ((diff < 0) ? -diff : diff);
663 }
664 Dest = resTemp;
665 '''
666 usad8Iop = InstObjParams("usad8", "Usad8", "RegRegRegOp",
667 { "code": usad8Code,
668 "predicate_test": predicateTest }, [])
669 header_output += RegRegRegOpDeclare.subst(usad8Iop)
670 decoder_output += RegRegRegOpConstructor.subst(usad8Iop)
671 exec_output += PredOpExecute.subst(usad8Iop)
672
673 usada8Code = '''
674 uint32_t resTemp = 0;
675 for (unsigned i = 0; i < 4; i++) {
676 int low = i * 8;
677 int high = low + 7;
678 int32_t diff = bits(Op1, high, low) -
679 bits(Op2, high, low);
680 resTemp += ((diff < 0) ? -diff : diff);
681 }
682 Dest = Op3 + resTemp;
683 '''
684 usada8Iop = InstObjParams("usada8", "Usada8", "RegRegRegRegOp",
685 { "code": usada8Code,
686 "predicate_test": predicateTest }, [])
687 header_output += RegRegRegRegOpDeclare.subst(usada8Iop)
688 decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop)
689 exec_output += PredOpExecute.subst(usada8Iop)
690
691 bkptCode = '''
692 uint16_t imm16;
693 if (!machInst.thumb)
694 imm16 = ((bits(machInst, 19, 8) << 4) | bits(machInst, 3, 0));
695 else
696 imm16 = bits(machInst, 7, 0);
697
698 return softwareBreakpoint32(xc, imm16);
699 '''
700 bkptIop = InstObjParams("bkpt", "BkptInst", "PredOp", bkptCode)
701 header_output += BasicDeclare.subst(bkptIop)
702 decoder_output += BasicConstructor.subst(bkptIop)
703 exec_output += BasicExecute.subst(bkptIop)
704
705 nopIop = InstObjParams("nop", "NopInst", "ArmStaticInst", "", ['IsNop'])
706 header_output += BasicDeclare.subst(nopIop)
707 decoder_output += BasicConstructor64.subst(nopIop)
708 exec_output += BasicExecute.subst(nopIop)
709
710 yieldIop = InstObjParams("yield", "YieldInst", "PredOp", \
711 { "code" : "", "predicate_test" : predicateTest })
712 header_output += BasicDeclare.subst(yieldIop)
713 decoder_output += BasicConstructor.subst(yieldIop)
714 exec_output += PredOpExecute.subst(yieldIop)
715
716 wfeCode = '''
717 CPSR cpsr = Cpsr;
718 SCR scr = Scr64;
719
720 // WFE Sleeps if SevMailbox==0 and no unmasked interrupts are pending,
721 ThreadContext *tc = xc->tcBase();
722 Tick next_cycle = tc->getCpuPtr()->nextCycle();
723 if (SevMailbox == 1) {
724 SevMailbox = 0;
725 tc->quiesceTick(next_cycle + 1);
726 } else if (tc->getCpuPtr()->getInterruptController(
727 tc->threadId())->checkInterrupts()) {
728 tc->quiesceTick(next_cycle + 1);
729 } else {
730 fault = trapWFx(tc, cpsr, scr, true);
731 if (fault == NoFault) {
732 tc->quiesce();
733 } else {
734 tc->quiesceTick(next_cycle + 1);
735 }
736 }
737 '''
738 wfePredFixUpCode = '''
739 // WFE is predicated false, reset SevMailbox to reduce spurious sleeps
740 // and SEV interrupts
741 SevMailbox = 1;
742 '''
743 wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \
744 { "code" : wfeCode,
745 "pred_fixup" : wfePredFixUpCode,
746 "predicate_test" : predicateTest },
747 ["IsNonSpeculative", "IsQuiesce",
748 "IsSerializeAfter", "IsUnverifiable"])
749 header_output += BasicDeclare.subst(wfeIop)
750 decoder_output += BasicConstructor.subst(wfeIop)
751 exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop)
752
753 wfiCode = '''
754 HCR hcr = Hcr;
755 CPSR cpsr = Cpsr;
756 SCR scr = Scr64;
757
758 // WFI doesn't sleep if interrupts are pending (masked or not)
759 ThreadContext *tc = xc->tcBase();
760 auto *ic = dynamic_cast<ArmISA::Interrupts *>(
761 tc->getCpuPtr()->getInterruptController(tc->threadId()));
762 Tick next_cycle = tc->getCpuPtr()->nextCycle();
763 if (ic->checkWfiWake(hcr, cpsr, scr)) {
764 tc->quiesceTick(next_cycle + 1);
765 } else {
766 fault = trapWFx(tc, cpsr, scr, false);
767 if (fault == NoFault) {
768 tc->quiesce();
769 ArmSystem::callSetStandByWfi(tc);
770 } else {
771 tc->quiesceTick(next_cycle + 1);
772 }
773 }
774 tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
775 '''
776 wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
777 { "code" : wfiCode, "predicate_test" : predicateTest },
778 ["IsNonSpeculative", "IsQuiesce",
779 "IsSerializeAfter", "IsUnverifiable"])
780 header_output += BasicDeclare.subst(wfiIop)
781 decoder_output += BasicConstructor.subst(wfiIop)
782 exec_output += QuiescePredOpExecute.subst(wfiIop)
783
784 sevCode = '''
785 SevMailbox = 1;
786 System *sys = xc->tcBase()->getSystemPtr();
787 for (int x = 0; x < sys->threads.size(); x++) {
788 ThreadContext *oc = sys->threads[x];
789 if (oc == xc->tcBase())
790 continue;
791
792 // Wake CPU with interrupt if they were sleeping
793 sendEvent(oc);
794 }
795 '''
796 sevIop = InstObjParams("sev", "SevInst", "PredOp", \
797 { "code" : sevCode, "predicate_test" : predicateTest },
798 ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"])
799 header_output += BasicDeclare.subst(sevIop)
800 decoder_output += BasicConstructor.subst(sevIop)
801 exec_output += PredOpExecute.subst(sevIop)
802
803 sevlCode = '''
804 SevMailbox = 1;
805 '''
806 sevlIop = InstObjParams("sevl", "SevlInst", "PredOp", \
807 { "code" : sevlCode, "predicate_test" : predicateTest },
808 ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"])
809 header_output += BasicDeclare.subst(sevlIop)
810 decoder_output += BasicConstructor.subst(sevlIop)
811 exec_output += BasicExecute.subst(sevlIop)
812
813 itIop = InstObjParams("it", "ItInst", "PredOp", \
814 { "code" : ";",
815 "predicate_test" : predicateTest }, [])
816 header_output += BasicDeclare.subst(itIop)
817 decoder_output += BasicConstructor.subst(itIop)
818 exec_output += PredOpExecute.subst(itIop)
819 unknownCode = '''
820 return std::make_shared<UndefinedInstruction>(machInst, true);
821 '''
822 unknownIop = InstObjParams("unknown", "Unknown", "UnknownOp", \
823 { "code": unknownCode,
824 "predicate_test": predicateTest })
825 header_output += BasicDeclare.subst(unknownIop)
826 decoder_output += BasicConstructor.subst(unknownIop)
827 exec_output += PredOpExecute.subst(unknownIop)
828
829 ubfxCode = '''
830 Dest = bits(Op1, imm2, imm1);
831 '''
832 ubfxIop = InstObjParams("ubfx", "Ubfx", "RegRegImmImmOp",
833 { "code": ubfxCode,
834 "predicate_test": predicateTest }, [])
835 header_output += RegRegImmImmOpDeclare.subst(ubfxIop)
836 decoder_output += RegRegImmImmOpConstructor.subst(ubfxIop)
837 exec_output += PredOpExecute.subst(ubfxIop)
838
839 sbfxCode = '''
840 int32_t resTemp = bits(Op1, imm2, imm1);
841 Dest = resTemp | -(resTemp & (1 << (imm2 - imm1)));
842 '''
843 sbfxIop = InstObjParams("sbfx", "Sbfx", "RegRegImmImmOp",
844 { "code": sbfxCode,
845 "predicate_test": predicateTest }, [])
846 header_output += RegRegImmImmOpDeclare.subst(sbfxIop)
847 decoder_output += RegRegImmImmOpConstructor.subst(sbfxIop)
848 exec_output += PredOpExecute.subst(sbfxIop)
849
850 bfcCode = '''
851 Dest = Op1 & ~(mask(imm2 - imm1 + 1) << imm1);
852 '''
853 bfcIop = InstObjParams("bfc", "Bfc", "RegRegImmImmOp",
854 { "code": bfcCode,
855 "predicate_test": predicateTest }, [])
856 header_output += RegRegImmImmOpDeclare.subst(bfcIop)
857 decoder_output += RegRegImmImmOpConstructor.subst(bfcIop)
858 exec_output += PredOpExecute.subst(bfcIop)
859
860 bfiCode = '''
861 uint32_t bitMask = (mask(imm2 - imm1 + 1) << imm1);
862 Dest = ((Op1 << imm1) & bitMask) | (Dest & ~bitMask);
863 '''
864 bfiIop = InstObjParams("bfi", "Bfi", "RegRegImmImmOp",
865 { "code": bfiCode,
866 "predicate_test": predicateTest }, [])
867 header_output += RegRegImmImmOpDeclare.subst(bfiIop)
868 decoder_output += RegRegImmImmOpConstructor.subst(bfiIop)
869 exec_output += PredOpExecute.subst(bfiIop)
870
871 mrc14code = '''
872 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
873 RegId(MiscRegClass, op1)).index();
874 bool can_read, undefined;
875 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr,
876 xc->tcBase());
877 if (!can_read || undefined) {
878 return std::make_shared<UndefinedInstruction>(machInst, false,
879 mnemonic);
880 }
881 if (mcrMrc14TrapToHyp((MiscRegIndex) op1, Hcr, Cpsr, Scr, Hdcr,
882 Hstr, Hcptr, imm)) {
883 return std::make_shared<HypervisorTrap>(machInst, imm,
884 EC_TRAPPED_CP14_MCR_MRC);
885 }
886 Dest = MiscOp1;
887 '''
888
889 mrc14Iop = InstObjParams("mrc", "Mrc14", "RegMiscRegImmOp",
890 { "code": mrc14code,
891 "predicate_test": predicateTest }, [])
892 header_output += RegMiscRegImmOpDeclare.subst(mrc14Iop)
893 decoder_output += RegMiscRegImmOpConstructor.subst(mrc14Iop)
894 exec_output += PredOpExecute.subst(mrc14Iop)
895
896
897 mcr14code = '''
898 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
899 RegId(MiscRegClass, dest)).index();
900 bool can_write, undefined;
901 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
902 xc->tcBase());
903 if (undefined || !can_write) {
904 return std::make_shared<UndefinedInstruction>(machInst, false,
905 mnemonic);
906 }
907 if (mcrMrc14TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr,
908 Hstr, Hcptr, imm)) {
909 return std::make_shared<HypervisorTrap>(machInst, imm,
910 EC_TRAPPED_CP14_MCR_MRC);
911 }
912 MiscDest = Op1;
913 '''
914 mcr14Iop = InstObjParams("mcr", "Mcr14", "MiscRegRegImmOp",
915 { "code": mcr14code,
916 "predicate_test": predicateTest },
917 ["IsSerializeAfter","IsNonSpeculative"])
918 header_output += MiscRegRegImmOpDeclare.subst(mcr14Iop)
919 decoder_output += MiscRegRegImmOpConstructor.subst(mcr14Iop)
920 exec_output += PredOpExecute.subst(mcr14Iop)
921
922 mrc15code = '''
923 int preFlatOp1 = snsBankedIndex(op1, xc->tcBase());
924 MiscRegIndex miscReg = (MiscRegIndex)
925 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
926 preFlatOp1)).index();
927
928 Fault fault = mcrMrc15Trap(miscReg, machInst, xc->tcBase(), imm);
929
930 bool can_read, undefined;
931 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr,
932 xc->tcBase());
933 // if we're in non secure PL1 mode then we can trap regargless of whether
934 // the register is accessable, in other modes we trap if only if the register
935 // IS accessable.
936 if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
937 !isSecure(xc->tcBase())))) {
938 return std::make_shared<UndefinedInstruction>(machInst, false,
939 mnemonic);
940 }
941 if (fault != NoFault) {
942 return fault;
943 }
944 Dest = MiscNsBankedOp1;
945 '''
946
947 mrc15Iop = InstObjParams("mrc", "Mrc15", "RegMiscRegImmOp",
948 { "code": mrc15code,
949 "predicate_test": predicateTest }, [])
950 header_output += RegMiscRegImmOpDeclare.subst(mrc15Iop)
951 decoder_output += RegMiscRegImmOpConstructor.subst(mrc15Iop)
952 exec_output += PredOpExecute.subst(mrc15Iop)
953
954
955 mcr15code = '''
956 int preFlatDest = snsBankedIndex(dest, xc->tcBase());
957 MiscRegIndex miscReg = (MiscRegIndex)
958 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
959 preFlatDest)).index();
960
961 Fault fault = mcrMrc15Trap(miscReg, machInst, xc->tcBase(), imm);
962
963 bool can_write, undefined;
964 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
965 xc->tcBase());
966
967 // if we're in non secure PL1 mode then we can trap regargless of whether
968 // the register is accessable, in other modes we trap if only if the register
969 // IS accessable.
970 if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
971 !isSecure(xc->tcBase())))) {
972 return std::make_shared<UndefinedInstruction>(machInst, false,
973 mnemonic);
974 }
975 if (fault != NoFault) {
976 return fault;
977 }
978 MiscNsBankedDest = Op1;
979 '''
980 mcr15Iop = InstObjParams("mcr", "Mcr15", "MiscRegRegImmOp",
981 { "code": mcr15code,
982 "predicate_test": predicateTest },
983 ["IsSerializeAfter","IsNonSpeculative"])
984 header_output += MiscRegRegImmOpDeclare.subst(mcr15Iop)
985 decoder_output += MiscRegRegImmOpConstructor.subst(mcr15Iop)
986 exec_output += PredOpExecute.subst(mcr15Iop)
987
988
989 mrrc15code = '''
990 int preFlatOp1 = snsBankedIndex(op1, xc->tcBase());
991 MiscRegIndex miscReg = (MiscRegIndex)
992 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
993 preFlatOp1)).index();
994
995 Fault fault = mcrrMrrc15Trap(miscReg, machInst, xc->tcBase(), imm);
996
997 bool can_read, undefined;
998 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr,
999 xc->tcBase());
1000 // if we're in non secure PL1 mode then we can trap regargless of whether
1001 // the register is accessable, in other modes we trap if only if the register
1002 // IS accessable.
1003 if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
1004 !isSecure(xc->tcBase())))) {
1005 return std::make_shared<UndefinedInstruction>(machInst, false,
1006 mnemonic);
1007 }
1008 if (fault != NoFault) {
1009 return fault;
1010 }
1011 Dest = bits(MiscNsBankedOp164, 63, 32);
1012 Dest2 = bits(MiscNsBankedOp164, 31, 0);
1013 '''
1014 mrrc15Iop = InstObjParams("mrrc", "Mrrc15", "MrrcOp",
1015 { "code": mrrc15code,
1016 "predicate_test": predicateTest }, [])
1017 header_output += MrrcOpDeclare.subst(mrrc15Iop)
1018 decoder_output += MrrcOpConstructor.subst(mrrc15Iop)
1019 exec_output += PredOpExecute.subst(mrrc15Iop)
1020
1021
1022 mcrr15code = '''
1023 int preFlatDest = snsBankedIndex(dest, xc->tcBase());
1024 MiscRegIndex miscReg = (MiscRegIndex)
1025 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
1026 preFlatDest)).index();
1027
1028 Fault fault = mcrrMrrc15Trap(miscReg, machInst, xc->tcBase(), imm);
1029
1030 bool can_write, undefined;
1031 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
1032 xc->tcBase());
1033
1034 // if we're in non secure PL1 mode then we can trap regargless of whether
1035 // the register is accessable, in other modes we trap if only if the register
1036 // IS accessable.
1037 if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
1038 !isSecure(xc->tcBase())))) {
1039 return std::make_shared<UndefinedInstruction>(machInst, false,
1040 mnemonic);
1041 }
1042 if (fault != NoFault) {
1043 return fault;
1044 }
1045 MiscNsBankedDest64 = ((uint64_t) Op1 << 32) | Op2;
1046 '''
1047 mcrr15Iop = InstObjParams("mcrr", "Mcrr15", "McrrOp",
1048 { "code": mcrr15code,
1049 "predicate_test": predicateTest }, [])
1050 header_output += McrrOpDeclare.subst(mcrr15Iop)
1051 decoder_output += McrrOpConstructor.subst(mcrr15Iop)
1052 exec_output += PredOpExecute.subst(mcrr15Iop)
1053
1054
1055 enterxCode = '''
1056 NextThumb = true;
1057 NextJazelle = true;
1058 '''
1059 enterxIop = InstObjParams("enterx", "Enterx", "PredOp",
1060 { "code": enterxCode,
1061 "predicate_test": predicateTest }, [])
1062 header_output += BasicDeclare.subst(enterxIop)
1063 decoder_output += BasicConstructor.subst(enterxIop)
1064 exec_output += PredOpExecute.subst(enterxIop)
1065
1066 leavexCode = '''
1067 NextThumb = true;
1068 NextJazelle = false;
1069 '''
1070 leavexIop = InstObjParams("leavex", "Leavex", "PredOp",
1071 { "code": leavexCode,
1072 "predicate_test": predicateTest }, [])
1073 header_output += BasicDeclare.subst(leavexIop)
1074 decoder_output += BasicConstructor.subst(leavexIop)
1075 exec_output += PredOpExecute.subst(leavexIop)
1076
1077 setendCode = '''
1078 CPSR cpsr = Cpsr;
1079 cpsr.e = imm;
1080 Cpsr = cpsr;
1081 fault = checkSETENDEnabled(xc->tcBase(), cpsr);
1082 '''
1083 setendIop = InstObjParams("setend", "Setend", "ImmOp",
1084 { "code": setendCode,
1085 "predicate_test": predicateTest },
1086 ["IsSerializeAfter","IsNonSpeculative"])
1087 header_output += ImmOpDeclare.subst(setendIop)
1088 decoder_output += ImmOpConstructor.subst(setendIop)
1089 exec_output += PredOpExecute.subst(setendIop)
1090
1091 clrexCode = '''
1092 LLSCLock = 0;
1093 '''
1094 clrexIop = InstObjParams("clrex", "Clrex","PredOp",
1095 { "code": clrexCode,
1096 "predicate_test": predicateTest },[])
1097 header_output += BasicDeclare.subst(clrexIop)
1098 decoder_output += BasicConstructor.subst(clrexIop)
1099 exec_output += PredOpExecute.subst(clrexIop)
1100
1101 McrDcCheckCode = '''
1102 int preFlatDest = snsBankedIndex(dest, xc->tcBase());
1103 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
1104 RegId(MiscRegClass, preFlatDest)).index();
1105
1106 bool hypTrap = mcrMrc15TrapToHyp(miscReg, xc->tcBase(), imm);
1107
1108 bool can_write, undefined;
1109 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
1110 xc->tcBase());
1111
1112 // if we're in non secure PL1 mode then we can trap regardless
1113 // of whether the register is accessible, in other modes we
1114 // trap if only if the register IS accessible.
1115 if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) &
1116 !isSecure(xc->tcBase())))) {
1117 return std::make_shared<UndefinedInstruction>(machInst, false,
1118 mnemonic);
1119 }
1120 if (hypTrap) {
1121 return std::make_shared<HypervisorTrap>(machInst, imm,
1122 EC_TRAPPED_CP15_MCR_MRC);
1123 }
1124 '''
1125
1126 McrDcimvacCode = '''
1127 const Request::Flags memAccessFlags(Request::INVALIDATE |
1128 Request::DST_POC);
1129 EA = Op1;
1130 '''
1131 McrDcimvacIop = InstObjParams("mcr", "McrDcimvac",
1132 "MiscRegRegImmOp",
1133 {"memacc_code": McrDcCheckCode,
1134 "postacc_code": "",
1135 "ea_code": McrDcimvacCode,
1136 "predicate_test": predicateTest},
1137 ['IsMemRef', 'IsStore'])
1138 header_output += MiscRegRegImmMemOpDeclare.subst(McrDcimvacIop)
1139 decoder_output += MiscRegRegImmOpConstructor.subst(McrDcimvacIop)
1140 exec_output += Mcr15Execute.subst(McrDcimvacIop) + \
1141 Mcr15InitiateAcc.subst(McrDcimvacIop) + \
1142 Mcr15CompleteAcc.subst(McrDcimvacIop)
1143
1144 McrDccmvacCode = '''
1145 const Request::Flags memAccessFlags(Request::CLEAN |
1146 Request::DST_POC);
1147 EA = Op1;
1148 '''
1149 McrDccmvacIop = InstObjParams("mcr", "McrDccmvac",
1150 "MiscRegRegImmOp",
1151 {"memacc_code": McrDcCheckCode,
1152 "postacc_code": "",
1153 "ea_code": McrDccmvacCode,
1154 "predicate_test": predicateTest},
1155 ['IsMemRef', 'IsStore'])
1156 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvacIop)
1157 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvacIop)
1158 exec_output += Mcr15Execute.subst(McrDccmvacIop) + \
1159 Mcr15InitiateAcc.subst(McrDccmvacIop) + \
1160 Mcr15CompleteAcc.subst(McrDccmvacIop)
1161
1162 McrDccmvauCode = '''
1163 const Request::Flags memAccessFlags(Request::CLEAN |
1164 Request::DST_POU);
1165 EA = Op1;
1166 '''
1167 McrDccmvauIop = InstObjParams("mcr", "McrDccmvau",
1168 "MiscRegRegImmOp",
1169 {"memacc_code": McrDcCheckCode,
1170 "postacc_code": "",
1171 "ea_code": McrDccmvauCode,
1172 "predicate_test": predicateTest},
1173 ['IsMemRef', 'IsStore'])
1174 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvauIop)
1175 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvauIop)
1176 exec_output += Mcr15Execute.subst(McrDccmvauIop) + \
1177 Mcr15InitiateAcc.subst(McrDccmvauIop) + \
1178 Mcr15CompleteAcc.subst(McrDccmvauIop)
1179
1180 McrDccimvacCode = '''
1181 const Request::Flags memAccessFlags(Request::CLEAN |
1182 Request::INVALIDATE |
1183 Request::DST_POC);
1184 EA = Op1;
1185 '''
1186 McrDccimvacIop = InstObjParams("mcr", "McrDccimvac",
1187 "MiscRegRegImmOp",
1188 {"memacc_code": McrDcCheckCode,
1189 "postacc_code": "",
1190 "ea_code": McrDccimvacCode,
1191 "predicate_test": predicateTest},
1192 ['IsMemRef', 'IsStore'])
1193 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccimvacIop)
1194 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccimvacIop)
1195 exec_output += Mcr15Execute.subst(McrDccimvacIop) + \
1196 Mcr15InitiateAcc.subst(McrDccimvacIop) + \
1197 Mcr15CompleteAcc.subst(McrDccimvacIop)
1198
1199 isbCode = '''
1200 // If the barrier is due to a CP15 access check for hyp traps
1201 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15ISB,
1202 xc->tcBase(), imm)) {
1203 return std::make_shared<HypervisorTrap>(machInst, imm,
1204 EC_TRAPPED_CP15_MCR_MRC);
1205 }
1206 '''
1207 isbIop = InstObjParams("isb", "Isb", "ImmOp",
1208 {"code": isbCode,
1209 "predicate_test": predicateTest},
1210 ['IsSquashAfter'])
1211 header_output += ImmOpDeclare.subst(isbIop)
1212 decoder_output += ImmOpConstructor.subst(isbIop)
1213 exec_output += PredOpExecute.subst(isbIop)
1214
1215 dsbCode = '''
1216 // If the barrier is due to a CP15 access check for hyp traps
1217 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15DSB,
1218 xc->tcBase(), imm)) {
1219 return std::make_shared<HypervisorTrap>(machInst, imm,
1220 EC_TRAPPED_CP15_MCR_MRC);
1221 }
1222 '''
1223 dsbIop = InstObjParams("dsb", "Dsb", "ImmOp",
1224 {"code": dsbCode,
1225 "predicate_test": predicateTest},
1226 ['IsMemBarrier', 'IsSerializeAfter'])
1227 header_output += ImmOpDeclare.subst(dsbIop)
1228 decoder_output += ImmOpConstructor.subst(dsbIop)
1229 exec_output += PredOpExecute.subst(dsbIop)
1230
1231 dmbCode = '''
1232 // If the barrier is due to a CP15 access check for hyp traps
1233 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15DMB,
1234 xc->tcBase(), imm)) {
1235 return std::make_shared<HypervisorTrap>(machInst, imm,
1236 EC_TRAPPED_CP15_MCR_MRC);
1237 }
1238 '''
1239 dmbIop = InstObjParams("dmb", "Dmb", "ImmOp",
1240 {"code": dmbCode,
1241 "predicate_test": predicateTest},
1242 ['IsMemBarrier'])
1243 header_output += ImmOpDeclare.subst(dmbIop)
1244 decoder_output += ImmOpConstructor.subst(dmbIop)
1245 exec_output += PredOpExecute.subst(dmbIop)
1246
1247 dbgCode = '''
1248 '''
1249 dbgIop = InstObjParams("dbg", "Dbg", "PredOp",
1250 {"code": dbgCode,
1251 "predicate_test": predicateTest})
1252 header_output += BasicDeclare.subst(dbgIop)
1253 decoder_output += BasicConstructor.subst(dbgIop)
1254 exec_output += PredOpExecute.subst(dbgIop)
1255
1256 cpsCode = '''
1257 uint32_t mode = bits(imm, 4, 0);
1258 uint32_t f = bits(imm, 5);
1259 uint32_t i = bits(imm, 6);
1260 uint32_t a = bits(imm, 7);
1261 bool setMode = bits(imm, 8);
1262 bool enable = bits(imm, 9);
1263 CPSR cpsr = Cpsr;
1264 SCTLR sctlr = Sctlr;
1265 if (cpsr.mode != MODE_USER) {
1266 if (enable) {
1267 if (f) cpsr.f = 0;
1268 if (i) cpsr.i = 0;
1269 if (a) cpsr.a = 0;
1270 } else {
1271 if (f && !sctlr.nmfi) cpsr.f = 1;
1272 if (i) cpsr.i = 1;
1273 if (a) cpsr.a = 1;
1274 }
1275 if (setMode) {
1276 cpsr.mode = mode;
1277 }
1278 }
1279 Cpsr = cpsr;
1280 '''
1281 cpsIop = InstObjParams("cps", "Cps", "ImmOp",
1282 { "code": cpsCode,
1283 "predicate_test": predicateTest },
1284 ["IsSerializeAfter","IsNonSpeculative"])
1285 header_output += ImmOpDeclare.subst(cpsIop)
1286 decoder_output += ImmOpConstructor.subst(cpsIop)
1287 exec_output += PredOpExecute.subst(cpsIop)
1288 }};