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