1// Copyright (c) 2008 The Hewlett-Packard Development Company
2// All rights reserved.
3//
4// The license below extends only to copyright in the software and shall
5// not be construed as granting a license to any other intellectual
6// property including but not limited to intellectual property relating
7// to a hardware implementation of the functionality of the software
8// licensed hereunder.  You may use the software subject to the license
9// terms below provided that you ensure that this notice is replicated
10// unmodified and in its entirety in all distributions of the software,
11// modified or unmodified, in source code or in binary form.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Gabe Black
37
38//////////////////////////////////////////////////////////////////////////
39//
40// Debug Microops
41//
42//////////////////////////////////////////////////////////////////////////
43
44output header {{
45    class MicroDebug : public X86ISA::X86MicroopBase
46    {
47      protected:
48        std::shared_ptr<GenericISA::M5DebugFault> fault;
49
50      public:
51        MicroDebug(ExtMachInst _machInst, const char *mnem,
52                const char *instMnem, uint64_t setFlags,
53                GenericISA::M5DebugFault *_fault);
54
55        Fault
56        execute(ExecContext *xc, Trace::InstRecord *traceData) const
57        {
58            return fault;
59        }
60
61        std::string
62        generateDisassembly(Addr pc, const SymbolTable *symtab) const
63        {
64            std::stringstream response;
65
66            printMnemonic(response, instMnem, mnemonic);
67            response << "\"" << fault->message() << "\"";
68
69            return response.str();
70        }
71    };
72
73    class MicroDebugFlags : public MicroDebug
74    {
75      protected:
76        uint8_t cc;
77
78      public:
79        MicroDebugFlags(ExtMachInst _machInst, const char *mnem,
80                const char *instMnem, uint64_t setFlags,
81                GenericISA::M5DebugFault *_fault, uint8_t _cc);
82
83        Fault execute(ExecContext *, Trace::InstRecord *) const;
84    };
85}};
86
87output decoder {{
88    MicroDebug::MicroDebug(ExtMachInst _machInst, const char *mnem,
89            const char *instMnem, uint64_t setFlags,
90            GenericISA::M5DebugFault *_fault) :
91        X86ISA::X86MicroopBase(_machInst, mnem, instMnem,
92                               setFlags, No_OpClass),
93        fault(_fault)
94    {}
95}};
96
97def template MicroDebugFlagsExecute {{
98        Fault
99        %(class_name)s::execute(ExecContext *xc,
100                Trace::InstRecord *traceData) const
101        {
102            %(op_decl)s
103            %(op_rd)s
104            if (%(cond_test)s) {
105                return %(base_class)s::execute(xc, traceData);
106            } else {
107                return NoFault;
108            }
109        }
110}};
111
112def template MicroDebugFlagsConstructor {{
113    %(class_name)s::%(class_name)s(
114            ExtMachInst machInst, const char *mnem,
115            const char *instMnem, uint64_t setFlags,
116            GenericISA::M5DebugFault *_fault, uint8_t _cc) :
117        %(base_class)s(machInst, mnem, instMnem, setFlags, _fault),
118        cc(_cc)
119    {
120        %(constructor)s;
121    }
122}};
123
124let {{
125    iop = InstObjParams("", "MicroDebugFlags", "MicroDebug",
126            {"code": "",
127             "cond_test": "checkCondition(ccFlagBits | cfofBits | \
128                                              dfBit | ecfBit | ezfBit, cc)"})
129    exec_output = MicroDebugFlagsExecute.subst(iop)
130    decoder_output = MicroDebugFlagsConstructor.subst(iop)
131}};
132
133let {{
134    class MicroDebug(X86Microop):
135        def __init__(self, name, fault, message, once, flags):
136            self.name = name
137            self.fault = fault
138            self.message = message
139            self.once = once
140            self.flags = flags
141            if flags and not isinstance(flags, (list, tuple)):
142                raise Exception, "flags must be a list or tuple of flags"
143
144            self.className = "MicroDebugFlags" if flags else "MicroDebug"
145
146        def getAllocator(self, microFlags):
147            if self.once:
148                fault_allocator_template = \
149                    "new %(fault_type)s(%(token)s, %(message)s)"
150            else:
151                fault_allocator_template = \
152                    "new %(fault_type)s(%(message)s)"
153            fault_allocator = fault_allocator_template % {
154                "fault_type": self.fault,
155                "token": "std::string(\"%s\")" % self.message,
156                "message": "\"%s\"" % self.message
157            }
158
159            args = ["machInst", "\"%s\"" % self.name, "macrocodeBlock",
160                self.microFlagsText(microFlags), fault_allocator]
161
162            if self.flags:
163                args.append(" | ".join(self.flags))
164
165            return "new " + self.className + "(" + ", ".join(args) + ")"
166
167    def buildDebugMicro(name, with_once=False):
168        global microopClasses
169
170        fault_class = "GenericISA::M5" + name.capitalize() + "Fault"
171
172        class MicroDebugChild(MicroDebug):
173            def __init__(self, message, flags=None):
174                super(MicroDebugChild, self).__init__(
175                        name, fault_class, message, False, flags)
176
177        microopClasses[name] = MicroDebugChild
178
179        if with_once:
180            fault_once_class = \
181                "GenericISA::M5" + name.capitalize() + "OnceFault"
182            name_once = name + "_once"
183
184            class MicroDebugOnceChild(MicroDebug):
185                def __init__(self, message, flags=None):
186                    super(MicroDebugOnceChild, self).__init__(
187                            name_once, fault_once_class, message, True, flags)
188
189            microopClasses[name_once] = MicroDebugOnceChild
190
191    buildDebugMicro("panic")
192    buildDebugMicro("fatal")
193    buildDebugMicro("hack", True)
194    buildDebugMicro("inform", True)
195    buildDebugMicro("warn", True)
196}};
197