1// -*- mode:c++ -*-
2
3// Copyright (c) 2007 MIPS Technologies, Inc.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Korey Sewell
30
31////////////////////////////////////////////////////////////////////
32//
33// Unimplemented instructions
34//
35
36output header {{
37    /**
38     * Static instruction class for unimplemented instructions that
39     * cause simulator termination.  Note that these are recognized
40     * (legal) instructions that the simulator does not support; the
41     * 'Unknown' class is used for unrecognized/illegal instructions.
42     * This is a leaf class.
43     */
44    class FailUnimplemented : public MipsStaticInst
45    {
46      public:
47        /// Constructor
48        FailUnimplemented(const char *_mnemonic, MachInst _machInst)
49            : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
50        {
51            // don't call execute() (which panics) if we're on a
52            // speculative path
53            flags[IsNonSpeculative] = true;
54        }
55
56        Fault execute(ExecContext *, Trace::InstRecord *) const override;
57
58        std::string generateDisassembly(
59                Addr pc, const SymbolTable *symtab) const override;
60    };
61    class CP0Unimplemented : public MipsStaticInst
62    {
63      public:
64        /// Constructor
65        CP0Unimplemented(const char *_mnemonic, MachInst _machInst)
66            : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
67        {
68            // don't call execute() (which panics) if we're on a
69            // speculative path
70            flags[IsNonSpeculative] = true;
71        }
72
73        Fault execute(ExecContext *, Trace::InstRecord *) const override;
74
75        std::string generateDisassembly(
76                Addr pc, const SymbolTable *symtab) const override;
77    };
78    class CP1Unimplemented : public MipsStaticInst
79    {
80      public:
81        /// Constructor
82        CP1Unimplemented(const char *_mnemonic, MachInst _machInst)
83            : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
84        {
85            // don't call execute() (which panics) if we're on a
86            // speculative path
87            flags[IsNonSpeculative] = true;
88        }
89
90        Fault execute(ExecContext *, Trace::InstRecord *) const override;
91
92        std::string generateDisassembly(
93                Addr pc, const SymbolTable *symtab) const override;
94    };
95    class CP2Unimplemented : public MipsStaticInst
96    {
97      public:
98        /// Constructor
99        CP2Unimplemented(const char *_mnemonic, MachInst _machInst)
100            : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
101        {
102            // don't call execute() (which panics) if we're on a
103            // speculative path
104            flags[IsNonSpeculative] = true;
105        }
106
107        Fault execute(ExecContext *, Trace::InstRecord *) const override;
108
109        std::string generateDisassembly(
110                Addr pc, const SymbolTable *symtab) const override;
111    };
112
113    /**
114     * Base class for unimplemented instructions that cause a warning
115     * to be printed (but do not terminate simulation).  This
116     * implementation is a little screwy in that it will print a
117     * warning for each instance of a particular unimplemented machine
118     * instruction, not just for each unimplemented opcode.  Should
119     * probably make the 'warned' flag a static member of the derived
120     * class.
121     */
122    class WarnUnimplemented : public MipsStaticInst
123    {
124      private:
125        /// Have we warned on this instruction yet?
126        mutable bool warned;
127
128      public:
129        /// Constructor
130        WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
131            : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
132        {
133            // don't call execute() (which panics) if we're on a
134            // speculative path
135            flags[IsNonSpeculative] = true;
136        }
137
138        Fault execute(ExecContext *, Trace::InstRecord *) const override;
139
140        std::string generateDisassembly(
141                Addr pc, const SymbolTable *symtab) const override;
142    };
143}};
144
145output decoder {{
146    std::string
147    FailUnimplemented::generateDisassembly(Addr pc,
148                                           const SymbolTable *symtab) const
149    {
150        return csprintf("%-10s (unimplemented)", mnemonic);
151    }
152
153    std::string
154    CP0Unimplemented::generateDisassembly(Addr pc,
155                                           const SymbolTable *symtab) const
156    {
157        return csprintf("%-10s (unimplemented)", mnemonic);
158    }
159
160    std::string
161    CP1Unimplemented::generateDisassembly(Addr pc,
162                                           const SymbolTable *symtab) const
163    {
164        return csprintf("%-10s (unimplemented)", mnemonic);
165    }
166    std::string
167    CP2Unimplemented::generateDisassembly(Addr pc,
168                                           const SymbolTable *symtab) const
169    {
170        return csprintf("%-10s (unimplemented)", mnemonic);
171    }
172
173    std::string
174    WarnUnimplemented::generateDisassembly(Addr pc,
175                                           const SymbolTable *symtab) const
176    {
177        return csprintf("%-10s (unimplemented)", mnemonic);
178    }
179}};
180
181output exec {{
182    Fault
183    FailUnimplemented::execute(ExecContext *xc,
184                               Trace::InstRecord *traceData) const
185    {
186        panic("attempt to execute unimplemented instruction '%s' "
187              "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
188              inst2string(machInst));
189        return NoFault;
190    }
191
192    Fault
193    CP0Unimplemented::execute(ExecContext *xc,
194                               Trace::InstRecord *traceData) const
195    {
196        if (FullSystem) {
197            if (!isCoprocessorEnabled(xc, 0))
198                return std::make_shared<CoprocessorUnusableFault>(0);
199            else
200                return std::make_shared<ReservedInstructionFault>();
201        } else {
202            panic("attempt to execute unimplemented instruction '%s' "
203                    "(inst %#08x, opcode %#x, binary:%s)",
204                    mnemonic, machInst, OPCODE, inst2string(machInst));
205            return NoFault;
206        }
207    }
208
209    Fault
210    CP1Unimplemented::execute(ExecContext *xc,
211                               Trace::InstRecord *traceData) const
212    {
213        if (FullSystem) {
214            if (!isCoprocessorEnabled(xc, 1))
215                return std::make_shared<CoprocessorUnusableFault>(1);
216            else
217                return std::make_shared<ReservedInstructionFault>();
218        } else {
219            panic("attempt to execute unimplemented instruction '%s' "
220                    "(inst %#08x, opcode %#x, binary:%s)",
221                    mnemonic, machInst, OPCODE, inst2string(machInst));
222            return NoFault;
223        }
224    }
225
226    Fault
227    CP2Unimplemented::execute(ExecContext *xc,
228                               Trace::InstRecord *traceData) const
229    {
230        if (FullSystem) {
231            if (!isCoprocessorEnabled(xc, 2))
232                return std::make_shared<CoprocessorUnusableFault>(2);
233            else
234                return std::make_shared<ReservedInstructionFault>();
235        } else {
236            panic("attempt to execute unimplemented instruction '%s' "
237                    "(inst %#08x, opcode %#x, binary:%s)",
238                    mnemonic, machInst, OPCODE, inst2string(machInst));
239            return NoFault;
240        }
241    }
242
243    Fault
244    WarnUnimplemented::execute(ExecContext *xc,
245                               Trace::InstRecord *traceData) const
246    {
247        if (!warned) {
248            warn("\tinstruction '%s' unimplemented\n", mnemonic);
249            warned = true;
250        }
251
252        return NoFault;
253    }
254}};
255
256
257def format FailUnimpl() {{
258    iop = InstObjParams(name, 'FailUnimplemented')
259    decode_block = BasicDecodeWithMnemonic.subst(iop)
260
261}};
262def format CP0Unimpl() {{
263    iop = InstObjParams(name, 'CP0Unimplemented')
264    decode_block = BasicDecodeWithMnemonic.subst(iop)
265}};
266def format CP1Unimpl() {{
267    iop = InstObjParams(name, 'CP1Unimplemented')
268    decode_block = BasicDecodeWithMnemonic.subst(iop)
269}};
270def format CP2Unimpl() {{
271    iop = InstObjParams(name, 'CP2Unimplemented')
272    decode_block = BasicDecodeWithMnemonic.subst(iop)
273}};
274def format WarnUnimpl() {{
275    iop = InstObjParams(name, 'WarnUnimplemented')
276    decode_block = BasicDecodeWithMnemonic.subst(iop)
277}};
278
279