1/*
2 * Copyright (c) 2010, 2012-2013, 2017-2018 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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 */
40
41#include "arch/arm/insts/misc.hh"
42
43#include "cpu/reg_class.hh"
44
45std::string
46MrsOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
47{
48    std::stringstream ss;
49    printMnemonic(ss);
50    printIntReg(ss, dest);
51    ss << ", ";
52    bool foundPsr = false;
53    for (unsigned i = 0; i < numSrcRegs(); i++) {
54        const RegId& reg = srcRegIdx(i);
55        if (!reg.isMiscReg()) {
56            continue;
57        }
58        if (reg.index() == MISCREG_CPSR) {
59            ss << "cpsr";
60            foundPsr = true;
61            break;
62        }
63        if (reg.index() == MISCREG_SPSR) {
64            ss << "spsr";
65            foundPsr = true;
66            break;
67        }
68    }
69    if (!foundPsr) {
70        ss << "????";
71    }
72    return ss.str();
73}
74
75void
76MsrBase::printMsrBase(std::ostream &os) const
77{
78    printMnemonic(os);
79    bool apsr = false;
80    bool foundPsr = false;
81    for (unsigned i = 0; i < numDestRegs(); i++) {
82        const RegId& reg = destRegIdx(i);
83        if (!reg.isMiscReg()) {
84            continue;
85        }
86        if (reg.index() == MISCREG_CPSR) {
87            os << "cpsr_";
88            foundPsr = true;
89            break;
90        }
91        if (reg.index() == MISCREG_SPSR) {
92            if (bits(byteMask, 1, 0)) {
93                os << "spsr_";
94            } else {
95                os << "apsr_";
96                apsr = true;
97            }
98            foundPsr = true;
99            break;
100        }
101    }
102    if (!foundPsr) {
103        os << "????";
104        return;
105    }
106    if (bits(byteMask, 3)) {
107        if (apsr) {
108            os << "nzcvq";
109        } else {
110            os << "f";
111        }
112    }
113    if (bits(byteMask, 2)) {
114        if (apsr) {
115            os << "g";
116        } else {
117            os << "s";
118        }
119    }
120    if (bits(byteMask, 1)) {
121        os << "x";
122    }
123    if (bits(byteMask, 0)) {
124        os << "c";
125    }
126}
127
128std::string
129MsrImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
130{
131    std::stringstream ss;
132    printMsrBase(ss);
133    ccprintf(ss, ", #%#x", imm);
134    return ss.str();
135}
136
137std::string
138MsrRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
139{
140    std::stringstream ss;
141    printMsrBase(ss);
142    ss << ", ";
143    printIntReg(ss, op1);
144    return ss.str();
145}
146
147std::string
148MrrcOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
149{
150    std::stringstream ss;
151    printMnemonic(ss);
152    printIntReg(ss, dest);
153    ss << ", ";
154    printIntReg(ss, dest2);
155    ss << ", ";
156    printMiscReg(ss, op1);
157    return ss.str();
158}
159
160std::string
161McrrOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
162{
163    std::stringstream ss;
164    printMnemonic(ss);
165    printMiscReg(ss, dest);
166    ss << ", ";
167    printIntReg(ss, op1);
168    ss << ", ";
169    printIntReg(ss, op2);
170    return ss.str();
171}
172
173std::string
174ImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
175{
176    std::stringstream ss;
177    printMnemonic(ss);
178    ccprintf(ss, "#%d", imm);
179    return ss.str();
180}
181
182std::string
183RegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
184{
185    std::stringstream ss;
186    printMnemonic(ss);
187    printIntReg(ss, dest);
188    ccprintf(ss, ", #%d", imm);
189    return ss.str();
190}
191
192std::string
193RegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
194{
195    std::stringstream ss;
196    printMnemonic(ss);
197    printIntReg(ss, dest);
198    ss << ", ";
199    printIntReg(ss, op1);
200    return ss.str();
201}
202
203std::string
204RegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
205{
206    std::stringstream ss;
207    printMnemonic(ss);
208    printIntReg(ss, dest);
209    ss << ", ";
210    printIntReg(ss, op1);
211    ss << ", ";
212    printIntReg(ss, op2);
213    ccprintf(ss, ", #%d", imm);
214    return ss.str();
215}
216
217std::string
218RegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
219{
220    std::stringstream ss;
221    printMnemonic(ss);
222    printIntReg(ss, dest);
223    ss << ", ";
224    printIntReg(ss, op1);
225    ss << ", ";
226    printIntReg(ss, op2);
227    ss << ", ";
228    printIntReg(ss, op3);
229    return ss.str();
230}
231
232std::string
233RegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
234{
235    std::stringstream ss;
236    printMnemonic(ss);
237    printIntReg(ss, dest);
238    ss << ", ";
239    printIntReg(ss, op1);
240    ss << ", ";
241    printIntReg(ss, op2);
242    return ss.str();
243}
244
245std::string
246RegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
247{
248    std::stringstream ss;
249    printMnemonic(ss);
250    printIntReg(ss, dest);
251    ss << ", ";
252    printIntReg(ss, op1);
253    ccprintf(ss, ", #%d", imm);
254    return ss.str();
255}
256
257std::string
258MiscRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
259{
260    std::stringstream ss;
261    printMnemonic(ss);
262    printMiscReg(ss, dest);
263    ss << ", ";
264    printIntReg(ss, op1);
265    return ss.str();
266}
267
268std::string
269RegMiscRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
270{
271    std::stringstream ss;
272    printMnemonic(ss);
273    printIntReg(ss, dest);
274    ss << ", ";
275    printMiscReg(ss, op1);
276    return ss.str();
277}
278
279std::string
280RegImmImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
281{
282    std::stringstream ss;
283    printMnemonic(ss);
284    printIntReg(ss, dest);
285    ccprintf(ss, ", #%d, #%d", imm1, imm2);
286    return ss.str();
287}
288
289std::string
290RegRegImmImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
291{
292    std::stringstream ss;
293    printMnemonic(ss);
294    printIntReg(ss, dest);
295    ss << ", ";
296    printIntReg(ss, op1);
297    ccprintf(ss, ", #%d, #%d", imm1, imm2);
298    return ss.str();
299}
300
301std::string
302RegImmRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
303{
304    std::stringstream ss;
305    printMnemonic(ss);
306    printIntReg(ss, dest);
307    ccprintf(ss, ", #%d, ", imm);
308    printIntReg(ss, op1);
309    return ss.str();
310}
311
312std::string
313RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
314{
315    std::stringstream ss;
316    printMnemonic(ss);
317    printIntReg(ss, dest);
318    ccprintf(ss, ", #%d, ", imm);
319    printShiftOperand(ss, op1, true, shiftAmt, INTREG_ZERO, shiftType);
320    printIntReg(ss, op1);
321    return ss.str();
322}
323
324std::string
325UnknownOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
326{
327    return csprintf("%-10s (inst %#08x)", "unknown", encoding());
328}
329
330McrMrcMiscInst::McrMrcMiscInst(const char *_mnemonic, ExtMachInst _machInst,
331                               uint64_t _iss, MiscRegIndex _miscReg)
332    : ArmStaticInst(_mnemonic, _machInst, No_OpClass)
333{
334    flags[IsNonSpeculative] = true;
335    iss = _iss;
336    miscReg = _miscReg;
337}
338
339Fault
340McrMrcMiscInst::execute(ExecContext *xc, Trace::InstRecord *traceData) const
341{
342    bool hypTrap = mcrMrc15TrapToHyp(miscReg, xc->tcBase(), iss);
343
344    if (hypTrap) {
345        return std::make_shared<HypervisorTrap>(machInst, iss,
346                                                EC_TRAPPED_CP15_MCR_MRC);
347    } else {
348        return NoFault;
349    }
350}
351
352std::string
353McrMrcMiscInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
354{
355    return csprintf("%-10s (pipe flush)", mnemonic);
356}
357
358McrMrcImplDefined::McrMrcImplDefined(const char *_mnemonic,
359                                     ExtMachInst _machInst, uint64_t _iss,
360                                     MiscRegIndex _miscReg)
361    : McrMrcMiscInst(_mnemonic, _machInst, _iss, _miscReg)
362{}
363
364Fault
365McrMrcImplDefined::execute(ExecContext *xc, Trace::InstRecord *traceData) const
366{
367    bool hypTrap = mcrMrc15TrapToHyp(miscReg, xc->tcBase(), iss);
368
369    if (hypTrap) {
370        return std::make_shared<HypervisorTrap>(machInst, iss,
371                                                EC_TRAPPED_CP15_MCR_MRC);
372    } else {
373        return std::make_shared<UndefinedInstruction>(machInst, false,
374                                                      mnemonic);
375    }
376}
377
378std::string
379McrMrcImplDefined::generateDisassembly(Addr pc,
380                                       const SymbolTable *symtab) const
381{
382    return csprintf("%-10s (implementation defined)", mnemonic);
383}
384