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