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