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