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