misc.isa (12358:386d26feb00f) misc.isa (12403:7be05f61abf3)
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 = '''
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 HCR hcr = Hcr;
674 CPSR cpsr = Cpsr;
675 SCR scr = Scr64;
673 CPSR cpsr = Cpsr;
674 SCR scr = Scr64;
676 SCTLR sctlr = Sctlr;
677
678 // WFE Sleeps if SevMailbox==0 and no unmasked interrupts are pending,
679 ThreadContext *tc = xc->tcBase();
680 if (SevMailbox == 1) {
681 SevMailbox = 0;
682 PseudoInst::quiesceSkip(tc);
683 } else if (tc->getCpuPtr()->getInterruptController(
684 tc->threadId())->checkInterrupts(tc)) {
685 PseudoInst::quiesceSkip(tc);
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);
686 } else if (cpsr.el == EL0 && !sctlr.ntwe) {
687 PseudoInst::quiesceSkip(tc);
688 fault = std::make_shared<SupervisorTrap>(machInst, 0x1E00001,
689 EC_TRAPPED_WFI_WFE);
690 } else if (ArmSystem::haveVirtualization(tc) &&
691 !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP) &&
692 hcr.twe) {
693 PseudoInst::quiesceSkip(tc);
694 fault = std::make_shared<HypervisorTrap>(machInst, 0x1E00001,
695 EC_TRAPPED_WFI_WFE);
696 } else if (ArmSystem::haveSecurity(tc) && cpsr.el != EL3 && scr.twe) {
697 PseudoInst::quiesceSkip(tc);
698 fault = std::make_shared<SecureMonitorTrap>(machInst, 0x1E00001,
699 EC_TRAPPED_WFI_WFE);
700 } else {
684 } else {
701 PseudoInst::quiesce(tc);
685 fault = trapWFx(tc, cpsr, scr, true);
686 if (fault == NoFault) {
687 PseudoInst::quiesce(tc);
688 } else {
689 PseudoInst::quiesceSkip(tc);
690 }
702 }
703 '''
704 wfePredFixUpCode = '''
705 // WFE is predicated false, reset SevMailbox to reduce spurious sleeps
706 // and SEV interrupts
707 SevMailbox = 1;
708 '''
709 wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \
710 { "code" : wfeCode,
711 "pred_fixup" : wfePredFixUpCode,
712 "predicate_test" : predicateTest },
713 ["IsNonSpeculative", "IsQuiesce",
714 "IsSerializeAfter", "IsUnverifiable"])
715 header_output += BasicDeclare.subst(wfeIop)
716 decoder_output += BasicConstructor.subst(wfeIop)
717 exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop)
718
719 wfiCode = '''
720 HCR hcr = Hcr;
721 CPSR cpsr = Cpsr;
722 SCR scr = Scr64;
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;
723 SCTLR sctlr = Sctlr;
724
725 // WFI doesn't sleep if interrupts are pending (masked or not)
726 ThreadContext *tc = xc->tcBase();
727 if (tc->getCpuPtr()->getInterruptController(
728 tc->threadId())->checkWfiWake(hcr, cpsr, scr)) {
729 PseudoInst::quiesceSkip(tc);
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);
730 } else if (cpsr.el == EL0 && !sctlr.ntwi) {
731 PseudoInst::quiesceSkip(tc);
732 fault = std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
733 EC_TRAPPED_WFI_WFE);
734 } else if (ArmSystem::haveVirtualization(tc) && hcr.twi &&
735 (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr)) {
736 PseudoInst::quiesceSkip(tc);
737 fault = std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
738 EC_TRAPPED_WFI_WFE);
739 } else if (ArmSystem::haveSecurity(tc) && cpsr.el != EL3 && scr.twi) {
740 PseudoInst::quiesceSkip(tc);
741 fault = std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
742 EC_TRAPPED_WFI_WFE);
743 } else {
718 } else {
744 PseudoInst::quiesce(tc);
719 fault = trapWFx(tc, cpsr, scr, false);
720 if (fault == NoFault) {
721 PseudoInst::quiesce(tc);
722 } else {
723 PseudoInst::quiesceSkip(tc);
724 }
745 }
746 tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
747 '''
748 wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
749 { "code" : wfiCode, "predicate_test" : predicateTest },
750 ["IsNonSpeculative", "IsQuiesce",
751 "IsSerializeAfter", "IsUnverifiable"])
752 header_output += BasicDeclare.subst(wfiIop)
753 decoder_output += BasicConstructor.subst(wfiIop)
754 exec_output += QuiescePredOpExecute.subst(wfiIop)
755
756 sevCode = '''
757 SevMailbox = 1;
758 System *sys = xc->tcBase()->getSystemPtr();
759 for (int x = 0; x < sys->numContexts(); x++) {
760 ThreadContext *oc = sys->getThreadContext(x);
761 if (oc == xc->tcBase())
762 continue;
763 // Wake CPU with interrupt if they were sleeping
764 if (oc->readMiscReg(MISCREG_SEV_MAILBOX) == 0) {
765 // Post Interrupt and wake cpu if needed
766 oc->getCpuPtr()->postInterrupt(oc->threadId(), INT_SEV, 0);
767 }
768 }
769 '''
770 sevIop = InstObjParams("sev", "SevInst", "PredOp", \
771 { "code" : sevCode, "predicate_test" : predicateTest },
772 ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"])
773 header_output += BasicDeclare.subst(sevIop)
774 decoder_output += BasicConstructor.subst(sevIop)
775 exec_output += PredOpExecute.subst(sevIop)
776
777 sevlCode = '''
778 SevMailbox = 1;
779 '''
780 sevlIop = InstObjParams("sevl", "SevlInst", "PredOp", \
781 { "code" : sevlCode, "predicate_test" : predicateTest },
782 ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"])
783 header_output += BasicDeclare.subst(sevlIop)
784 decoder_output += BasicConstructor.subst(sevlIop)
785 exec_output += BasicExecute.subst(sevlIop)
786
787 itIop = InstObjParams("it", "ItInst", "PredOp", \
788 { "code" : ";",
789 "predicate_test" : predicateTest }, [])
790 header_output += BasicDeclare.subst(itIop)
791 decoder_output += BasicConstructor.subst(itIop)
792 exec_output += PredOpExecute.subst(itIop)
793 unknownCode = '''
794 return std::make_shared<UndefinedInstruction>(machInst, true);
795 '''
796 unknownIop = InstObjParams("unknown", "Unknown", "UnknownOp", \
797 { "code": unknownCode,
798 "predicate_test": predicateTest })
799 header_output += BasicDeclare.subst(unknownIop)
800 decoder_output += BasicConstructor.subst(unknownIop)
801 exec_output += PredOpExecute.subst(unknownIop)
802
803 ubfxCode = '''
804 Dest = bits(Op1, imm2, imm1);
805 '''
806 ubfxIop = InstObjParams("ubfx", "Ubfx", "RegRegImmImmOp",
807 { "code": ubfxCode,
808 "predicate_test": predicateTest }, [])
809 header_output += RegRegImmImmOpDeclare.subst(ubfxIop)
810 decoder_output += RegRegImmImmOpConstructor.subst(ubfxIop)
811 exec_output += PredOpExecute.subst(ubfxIop)
812
813 sbfxCode = '''
814 int32_t resTemp = bits(Op1, imm2, imm1);
815 Dest = resTemp | -(resTemp & (1 << (imm2 - imm1)));
816 '''
817 sbfxIop = InstObjParams("sbfx", "Sbfx", "RegRegImmImmOp",
818 { "code": sbfxCode,
819 "predicate_test": predicateTest }, [])
820 header_output += RegRegImmImmOpDeclare.subst(sbfxIop)
821 decoder_output += RegRegImmImmOpConstructor.subst(sbfxIop)
822 exec_output += PredOpExecute.subst(sbfxIop)
823
824 bfcCode = '''
825 Dest = Op1 & ~(mask(imm2 - imm1 + 1) << imm1);
826 '''
827 bfcIop = InstObjParams("bfc", "Bfc", "RegRegImmImmOp",
828 { "code": bfcCode,
829 "predicate_test": predicateTest }, [])
830 header_output += RegRegImmImmOpDeclare.subst(bfcIop)
831 decoder_output += RegRegImmImmOpConstructor.subst(bfcIop)
832 exec_output += PredOpExecute.subst(bfcIop)
833
834 bfiCode = '''
835 uint32_t bitMask = (mask(imm2 - imm1 + 1) << imm1);
836 Dest = ((Op1 << imm1) & bitMask) | (Dest & ~bitMask);
837 '''
838 bfiIop = InstObjParams("bfi", "Bfi", "RegRegImmImmOp",
839 { "code": bfiCode,
840 "predicate_test": predicateTest }, [])
841 header_output += RegRegImmImmOpDeclare.subst(bfiIop)
842 decoder_output += RegRegImmImmOpConstructor.subst(bfiIop)
843 exec_output += PredOpExecute.subst(bfiIop)
844
845 mrc14code = '''
846 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
847 RegId(MiscRegClass, op1)).index();
848 bool can_read, undefined;
849 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
850 if (!can_read || undefined) {
851 return std::make_shared<UndefinedInstruction>(machInst, false,
852 mnemonic);
853 }
854 if (mcrMrc14TrapToHyp((const MiscRegIndex) op1, Hcr, Cpsr, Scr, Hdcr,
855 Hstr, Hcptr, imm)) {
856 return std::make_shared<HypervisorTrap>(machInst, imm,
857 EC_TRAPPED_CP14_MCR_MRC);
858 }
859 Dest = MiscOp1;
860 '''
861
862 mrc14Iop = InstObjParams("mrc", "Mrc14", "RegRegImmOp",
863 { "code": mrc14code,
864 "predicate_test": predicateTest }, [])
865 header_output += RegRegImmOpDeclare.subst(mrc14Iop)
866 decoder_output += RegRegImmOpConstructor.subst(mrc14Iop)
867 exec_output += PredOpExecute.subst(mrc14Iop)
868
869
870 mcr14code = '''
871 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
872 RegId(MiscRegClass, dest)).index();
873 bool can_write, undefined;
874 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
875 if (undefined || !can_write) {
876 return std::make_shared<UndefinedInstruction>(machInst, false,
877 mnemonic);
878 }
879 if (mcrMrc14TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr,
880 Hstr, Hcptr, imm)) {
881 return std::make_shared<HypervisorTrap>(machInst, imm,
882 EC_TRAPPED_CP14_MCR_MRC);
883 }
884 MiscDest = Op1;
885 '''
886 mcr14Iop = InstObjParams("mcr", "Mcr14", "RegRegImmOp",
887 { "code": mcr14code,
888 "predicate_test": predicateTest },
889 ["IsSerializeAfter","IsNonSpeculative"])
890 header_output += RegRegImmOpDeclare.subst(mcr14Iop)
891 decoder_output += RegRegImmOpConstructor.subst(mcr14Iop)
892 exec_output += PredOpExecute.subst(mcr14Iop)
893
894 mrc15code = '''
895 int preFlatOp1 = flattenMiscRegNsBanked(op1, xc->tcBase());
896 MiscRegIndex miscReg = (MiscRegIndex)
897 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
898 preFlatOp1)).index();
899 bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
900 Hcptr, imm);
901 bool can_read, undefined;
902 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
903 // if we're in non secure PL1 mode then we can trap regargless of whether
904 // the register is accessable, in other modes we trap if only if the register
905 // IS accessable.
906 if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) &&
907 !inSecureState(Scr, Cpsr)))) {
908 return std::make_shared<UndefinedInstruction>(machInst, false,
909 mnemonic);
910 }
911 if (hypTrap) {
912 return std::make_shared<HypervisorTrap>(machInst, imm,
913 EC_TRAPPED_CP15_MCR_MRC);
914 }
915 Dest = MiscNsBankedOp1;
916 '''
917
918 mrc15Iop = InstObjParams("mrc", "Mrc15", "RegMiscRegImmOp",
919 { "code": mrc15code,
920 "predicate_test": predicateTest }, [])
921 header_output += RegMiscRegImmOpDeclare.subst(mrc15Iop)
922 decoder_output += RegMiscRegImmOpConstructor.subst(mrc15Iop)
923 exec_output += PredOpExecute.subst(mrc15Iop)
924
925
926 mcr15code = '''
927 int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
928 MiscRegIndex miscReg = (MiscRegIndex)
929 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
930 preFlatDest)).index();
931 bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
932 Hcptr, imm);
933 bool can_write, undefined;
934 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
935
936 // if we're in non secure PL1 mode then we can trap regargless of whether
937 // the register is accessable, in other modes we trap if only if the register
938 // IS accessable.
939 if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) &&
940 !inSecureState(Scr, Cpsr)))) {
941 return std::make_shared<UndefinedInstruction>(machInst, false,
942 mnemonic);
943 }
944 if (hypTrap) {
945 return std::make_shared<HypervisorTrap>(machInst, imm,
946 EC_TRAPPED_CP15_MCR_MRC);
947 }
948 MiscNsBankedDest = Op1;
949 '''
950 mcr15Iop = InstObjParams("mcr", "Mcr15", "MiscRegRegImmOp",
951 { "code": mcr15code,
952 "predicate_test": predicateTest },
953 ["IsSerializeAfter","IsNonSpeculative"])
954 header_output += MiscRegRegImmOpDeclare.subst(mcr15Iop)
955 decoder_output += MiscRegRegImmOpConstructor.subst(mcr15Iop)
956 exec_output += PredOpExecute.subst(mcr15Iop)
957
958
959 mrrc15code = '''
960 int preFlatOp1 = flattenMiscRegNsBanked(op1, xc->tcBase());
961 MiscRegIndex miscReg = (MiscRegIndex)
962 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
963 preFlatOp1)).index();
964 bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
965 bool can_read, undefined;
966 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
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_read && !(hypTrap && !inUserMode(Cpsr) &&
971 !inSecureState(Scr, Cpsr)))) {
972 return std::make_shared<UndefinedInstruction>(machInst, false,
973 mnemonic);
974 }
975 if (hypTrap) {
976 return std::make_shared<HypervisorTrap>(machInst, imm,
977 EC_TRAPPED_CP15_MCRR_MRRC);
978 }
979 Dest = bits(MiscNsBankedOp164, 63, 32);
980 Dest2 = bits(MiscNsBankedOp164, 31, 0);
981 '''
982 mrrc15Iop = InstObjParams("mrrc", "Mrrc15", "MrrcOp",
983 { "code": mrrc15code,
984 "predicate_test": predicateTest }, [])
985 header_output += MrrcOpDeclare.subst(mrrc15Iop)
986 decoder_output += MrrcOpConstructor.subst(mrrc15Iop)
987 exec_output += PredOpExecute.subst(mrrc15Iop)
988
989
990 mcrr15code = '''
991 int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
992 MiscRegIndex miscReg = (MiscRegIndex)
993 xc->tcBase()->flattenRegId(RegId(MiscRegClass,
994 preFlatDest)).index();
995 bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
996 bool can_write, undefined;
997 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
998
999 // if we're in non secure PL1 mode then we can trap regargless of whether
1000 // the register is accessable, in other modes we trap if only if the register
1001 // IS accessable.
1002 if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) &&
1003 !inSecureState(Scr, Cpsr)))) {
1004 return std::make_shared<UndefinedInstruction>(machInst, false,
1005 mnemonic);
1006 }
1007 if (hypTrap) {
1008 return std::make_shared<HypervisorTrap>(machInst, imm,
1009 EC_TRAPPED_CP15_MCRR_MRRC);
1010 }
1011 MiscNsBankedDest64 = ((uint64_t) Op1 << 32) | Op2;
1012 '''
1013 mcrr15Iop = InstObjParams("mcrr", "Mcrr15", "McrrOp",
1014 { "code": mcrr15code,
1015 "predicate_test": predicateTest }, [])
1016 header_output += McrrOpDeclare.subst(mcrr15Iop)
1017 decoder_output += McrrOpConstructor.subst(mcrr15Iop)
1018 exec_output += PredOpExecute.subst(mcrr15Iop)
1019
1020
1021 enterxCode = '''
1022 NextThumb = true;
1023 NextJazelle = true;
1024 '''
1025 enterxIop = InstObjParams("enterx", "Enterx", "PredOp",
1026 { "code": enterxCode,
1027 "predicate_test": predicateTest }, [])
1028 header_output += BasicDeclare.subst(enterxIop)
1029 decoder_output += BasicConstructor.subst(enterxIop)
1030 exec_output += PredOpExecute.subst(enterxIop)
1031
1032 leavexCode = '''
1033 NextThumb = true;
1034 NextJazelle = false;
1035 '''
1036 leavexIop = InstObjParams("leavex", "Leavex", "PredOp",
1037 { "code": leavexCode,
1038 "predicate_test": predicateTest }, [])
1039 header_output += BasicDeclare.subst(leavexIop)
1040 decoder_output += BasicConstructor.subst(leavexIop)
1041 exec_output += PredOpExecute.subst(leavexIop)
1042
1043 setendCode = '''
1044 CPSR cpsr = Cpsr;
1045 cpsr.e = imm;
1046 Cpsr = cpsr;
1047 '''
1048 setendIop = InstObjParams("setend", "Setend", "ImmOp",
1049 { "code": setendCode,
1050 "predicate_test": predicateTest },
1051 ["IsSerializeAfter","IsNonSpeculative"])
1052 header_output += ImmOpDeclare.subst(setendIop)
1053 decoder_output += ImmOpConstructor.subst(setendIop)
1054 exec_output += PredOpExecute.subst(setendIop)
1055
1056 clrexCode = '''
1057 LLSCLock = 0;
1058 '''
1059 clrexIop = InstObjParams("clrex", "Clrex","PredOp",
1060 { "code": clrexCode,
1061 "predicate_test": predicateTest },[])
1062 header_output += BasicDeclare.subst(clrexIop)
1063 decoder_output += BasicConstructor.subst(clrexIop)
1064 exec_output += PredOpExecute.subst(clrexIop)
1065
1066 McrDcCheckCode = '''
1067 int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
1068 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
1069 RegId(MiscRegClass, preFlatDest)).index();
1070 bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
1071 Hcptr, imm);
1072 bool can_write, undefined;
1073 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
1074
1075 // if we're in non secure PL1 mode then we can trap regardless
1076 // of whether the register is accessible, in other modes we
1077 // trap if only if the register IS accessible.
1078 if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) &
1079 !inSecureState(Scr, Cpsr)))) {
1080 return std::make_shared<UndefinedInstruction>(machInst, false,
1081 mnemonic);
1082 }
1083 if (hypTrap) {
1084 return std::make_shared<HypervisorTrap>(machInst, imm,
1085 EC_TRAPPED_CP15_MCR_MRC);
1086 }
1087 '''
1088
1089 McrDcimvacCode = '''
1090 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
1091 Request::INVALIDATE |
1092 Request::DST_POC);
1093 EA = Op1;
1094 '''
1095 McrDcimvacIop = InstObjParams("mcr dcimvac", "McrDcimvac",
1096 "MiscRegRegImmMemOp",
1097 {"memacc_code": McrDcCheckCode,
1098 "postacc_code": "",
1099 "ea_code": McrDcimvacCode,
1100 "predicate_test": predicateTest},
1101 ['IsMemRef', 'IsStore'])
1102 header_output += MiscRegRegImmMemOpDeclare.subst(McrDcimvacIop)
1103 decoder_output += MiscRegRegImmOpConstructor.subst(McrDcimvacIop)
1104 exec_output += Mcr15Execute.subst(McrDcimvacIop) + \
1105 Mcr15InitiateAcc.subst(McrDcimvacIop) + \
1106 Mcr15CompleteAcc.subst(McrDcimvacIop)
1107
1108 McrDccmvacCode = '''
1109 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
1110 Request::CLEAN |
1111 Request::DST_POC);
1112 EA = Op1;
1113 '''
1114 McrDccmvacIop = InstObjParams("mcr dccmvac", "McrDccmvac",
1115 "MiscRegRegImmMemOp",
1116 {"memacc_code": McrDcCheckCode,
1117 "postacc_code": "",
1118 "ea_code": McrDccmvacCode,
1119 "predicate_test": predicateTest},
1120 ['IsMemRef', 'IsStore'])
1121 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvacIop)
1122 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvacIop)
1123 exec_output += Mcr15Execute.subst(McrDccmvacIop) + \
1124 Mcr15InitiateAcc.subst(McrDccmvacIop) + \
1125 Mcr15CompleteAcc.subst(McrDccmvacIop)
1126
1127 McrDccmvauCode = '''
1128 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
1129 Request::CLEAN |
1130 Request::DST_POU);
1131 EA = Op1;
1132 '''
1133 McrDccmvauIop = InstObjParams("mcr dccmvau", "McrDccmvau",
1134 "MiscRegRegImmMemOp",
1135 {"memacc_code": McrDcCheckCode,
1136 "postacc_code": "",
1137 "ea_code": McrDccmvauCode,
1138 "predicate_test": predicateTest},
1139 ['IsMemRef', 'IsStore'])
1140 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvauIop)
1141 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvauIop)
1142 exec_output += Mcr15Execute.subst(McrDccmvauIop) + \
1143 Mcr15InitiateAcc.subst(McrDccmvauIop) + \
1144 Mcr15CompleteAcc.subst(McrDccmvauIop)
1145
1146 McrDccimvacCode = '''
1147 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
1148 Request::CLEAN |
1149 Request::INVALIDATE |
1150 Request::DST_POC);
1151 EA = Op1;
1152 '''
1153 McrDccimvacIop = InstObjParams("mcr dccimvac", "McrDccimvac",
1154 "MiscRegRegImmMemOp",
1155 {"memacc_code": McrDcCheckCode,
1156 "postacc_code": "",
1157 "ea_code": McrDccimvacCode,
1158 "predicate_test": predicateTest},
1159 ['IsMemRef', 'IsStore'])
1160 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccimvacIop)
1161 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccimvacIop)
1162 exec_output += Mcr15Execute.subst(McrDccimvacIop) + \
1163 Mcr15InitiateAcc.subst(McrDccimvacIop) + \
1164 Mcr15CompleteAcc.subst(McrDccimvacIop)
1165
1166 isbCode = '''
1167 // If the barrier is due to a CP15 access check for hyp traps
1168 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15ISB, Hcr, Cpsr, Scr,
1169 Hdcr, Hstr, Hcptr, imm)) {
1170 return std::make_shared<HypervisorTrap>(machInst, imm,
1171 EC_TRAPPED_CP15_MCR_MRC);
1172 }
1173 '''
1174 isbIop = InstObjParams("isb", "Isb", "ImmOp",
1175 {"code": isbCode,
1176 "predicate_test": predicateTest},
1177 ['IsSerializeAfter', 'IsSquashAfter'])
1178 header_output += ImmOpDeclare.subst(isbIop)
1179 decoder_output += ImmOpConstructor.subst(isbIop)
1180 exec_output += PredOpExecute.subst(isbIop)
1181
1182 dsbCode = '''
1183 // If the barrier is due to a CP15 access check for hyp traps
1184 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15DSB, Hcr, Cpsr, Scr,
1185 Hdcr, Hstr, Hcptr, imm)) {
1186 return std::make_shared<HypervisorTrap>(machInst, imm,
1187 EC_TRAPPED_CP15_MCR_MRC);
1188 }
1189 '''
1190 dsbIop = InstObjParams("dsb", "Dsb", "ImmOp",
1191 {"code": dsbCode,
1192 "predicate_test": predicateTest},
1193 ['IsMemBarrier', 'IsSerializeAfter'])
1194 header_output += ImmOpDeclare.subst(dsbIop)
1195 decoder_output += ImmOpConstructor.subst(dsbIop)
1196 exec_output += PredOpExecute.subst(dsbIop)
1197
1198 dmbCode = '''
1199 // If the barrier is due to a CP15 access check for hyp traps
1200 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15DMB, Hcr, Cpsr, Scr,
1201 Hdcr, Hstr, Hcptr, imm)) {
1202 return std::make_shared<HypervisorTrap>(machInst, imm,
1203 EC_TRAPPED_CP15_MCR_MRC);
1204 }
1205 '''
1206 dmbIop = InstObjParams("dmb", "Dmb", "ImmOp",
1207 {"code": dmbCode,
1208 "predicate_test": predicateTest},
1209 ['IsMemBarrier'])
1210 header_output += ImmOpDeclare.subst(dmbIop)
1211 decoder_output += ImmOpConstructor.subst(dmbIop)
1212 exec_output += PredOpExecute.subst(dmbIop)
1213
1214 dbgCode = '''
1215 '''
1216 dbgIop = InstObjParams("dbg", "Dbg", "PredOp",
1217 {"code": dbgCode,
1218 "predicate_test": predicateTest})
1219 header_output += BasicDeclare.subst(dbgIop)
1220 decoder_output += BasicConstructor.subst(dbgIop)
1221 exec_output += PredOpExecute.subst(dbgIop)
1222
1223 cpsCode = '''
1224 uint32_t mode = bits(imm, 4, 0);
1225 uint32_t f = bits(imm, 5);
1226 uint32_t i = bits(imm, 6);
1227 uint32_t a = bits(imm, 7);
1228 bool setMode = bits(imm, 8);
1229 bool enable = bits(imm, 9);
1230 CPSR cpsr = Cpsr;
1231 SCTLR sctlr = Sctlr;
1232 if (cpsr.mode != MODE_USER) {
1233 if (enable) {
1234 if (f) cpsr.f = 0;
1235 if (i) cpsr.i = 0;
1236 if (a) cpsr.a = 0;
1237 } else {
1238 if (f && !sctlr.nmfi) cpsr.f = 1;
1239 if (i) cpsr.i = 1;
1240 if (a) cpsr.a = 1;
1241 }
1242 if (setMode) {
1243 cpsr.mode = mode;
1244 }
1245 }
1246 Cpsr = cpsr;
1247 '''
1248 cpsIop = InstObjParams("cps", "Cps", "ImmOp",
1249 { "code": cpsCode,
1250 "predicate_test": predicateTest },
1251 ["IsSerializeAfter","IsNonSpeculative"])
1252 header_output += ImmOpDeclare.subst(cpsIop)
1253 decoder_output += ImmOpConstructor.subst(cpsIop)
1254 exec_output += PredOpExecute.subst(cpsIop)
1255}};
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}};