1// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
2// Copyright (c) 2011 Mark D. Hill and David A. Wood
3// All rights reserved.
4//
5// The license below extends only to copyright in the software and shall
6// not be construed as granting a license to any other intellectual
7// property including but not limited to intellectual property relating
8// to a hardware implementation of the functionality of the software
9// licensed hereunder.  You may use the software subject to the license
10// terms below provided that you ensure that this notice is replicated
11// unmodified and in its entirety in all distributions of the software,
12// modified or unmodified, in source code or in binary form.
13//
14// Redistribution and use in source and binary forms, with or without
15// modification, are permitted provided that the following conditions are
16// met: redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer;
18// redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution;
21// neither the name of the copyright holders nor the names of its
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Authors: Gabe Black
38
39//////////////////////////////////////////////////////////////////////////
40//
41// Fault Microop
42//
43//////////////////////////////////////////////////////////////////////////
44
45output header {{
46    class MicroFaultBase : public X86ISA::X86MicroopBase
47    {
48      protected:
49        Fault fault;
50        uint8_t cc;
51
52      public:
53        MicroFaultBase(ExtMachInst _machInst, const char * instMnem,
54                uint64_t setFlags, Fault _fault, uint8_t _cc);
55
56        std::string generateDisassembly(Addr pc,
57                const SymbolTable *symtab) const;
58    };
59
60    class MicroHalt : public X86ISA::X86MicroopBase
61    {
62      public:
63        MicroHalt(ExtMachInst _machInst, const char * instMnem,
64                uint64_t setFlags) :
65            X86MicroopBase(_machInst, "halt", instMnem,
66                           setFlags | (ULL(1) << StaticInst::IsNonSpeculative) |
67                           (ULL(1) << StaticInst::IsQuiesce),
68                           No_OpClass)
69        {
70        }
71
72        Fault execute(ExecContext *, Trace::InstRecord *) const;
73
74        std::string generateDisassembly(Addr pc,
75                const SymbolTable *symtab) const;
76    };
77}};
78
79def template MicroFaultDeclare {{
80    class %(class_name)s : public %(base_class)s
81    {
82      public:
83        %(class_name)s(ExtMachInst _machInst, const char * instMnem,
84                uint64_t setFlags, Fault _fault, uint8_t _cc);
85
86        Fault execute(ExecContext *, Trace::InstRecord *) const;
87    };
88}};
89
90def template MicroFaultExecute {{
91        Fault %(class_name)s::execute(ExecContext *xc,
92                Trace::InstRecord *traceData) const
93        {
94            %(op_decl)s;
95            %(op_rd)s;
96            if (%(cond_test)s) {
97                //Return the fault we were constructed with
98                return fault;
99            } else {
100                return NoFault;
101            }
102        }
103}};
104
105output exec {{
106    Fault
107    MicroHalt::execute(ExecContext *xc, Trace::InstRecord * traceData) const
108    {
109        xc->tcBase()->suspend();
110        return NoFault;
111    }
112}};
113
114output decoder {{
115    MicroFaultBase::MicroFaultBase(
116            ExtMachInst machInst, const char * instMnem,
117            uint64_t setFlags, Fault _fault, uint8_t _cc) :
118        X86MicroopBase(machInst, "fault", instMnem, setFlags, No_OpClass),
119                fault(_fault), cc(_cc)
120    {
121    }
122}};
123
124def template MicroFaultConstructor {{
125    %(class_name)s::%(class_name)s(
126            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
127            Fault _fault, uint8_t _cc) :
128        %(base_class)s(machInst, instMnem, setFlags, _fault, _cc)
129    {
130        %(constructor)s;
131    }
132}};
133
134output decoder {{
135    std::string MicroFaultBase::generateDisassembly(Addr pc,
136            const SymbolTable *symtab) const
137    {
138        std::stringstream response;
139
140        printMnemonic(response, instMnem, mnemonic);
141        if(fault)
142            response << fault->name();
143        else
144            response << "No Fault";
145
146        return response.str();
147    }
148
149    std::string MicroHalt::generateDisassembly(Addr pc,
150            const SymbolTable *symtab) const
151    {
152        std::stringstream response;
153
154        printMnemonic(response, instMnem, mnemonic);
155
156        return response.str();
157    }
158}};
159
160let {{
161    class Fault(X86Microop):
162        className = "MicroFault"
163        def __init__(self, fault, flags=None):
164            self.fault = fault
165            if flags:
166                if not isinstance(flags, (list, tuple)):
167                    raise Exception, "flags must be a list or tuple of flags"
168                self.cond = " | ".join(flags)
169                self.className += "Flags"
170            else:
171                self.cond = "0"
172
173        def getAllocator(self, microFlags):
174            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
175                    %(flags)s, %(fault)s, %(cc)s)''' % {
176                "class_name" : self.className,
177                "flags" : self.microFlagsText(microFlags),
178                "fault" : self.fault,
179                "cc" : self.cond}
180            return allocator
181
182    iop = InstObjParams("fault", "MicroFaultFlags", "MicroFaultBase",
183            {"code": "",
184             "cond_test": "checkCondition(ccFlagBits | cfofBits | dfBit | \
185                                          ecfBit | ezfBit, cc)"})
186    exec_output = MicroFaultExecute.subst(iop)
187    header_output = MicroFaultDeclare.subst(iop)
188    decoder_output = MicroFaultConstructor.subst(iop)
189    iop = InstObjParams("fault", "MicroFault", "MicroFaultBase",
190            {"code": "",
191             "cond_test": "true"})
192    exec_output += MicroFaultExecute.subst(iop)
193    header_output += MicroFaultDeclare.subst(iop)
194    decoder_output += MicroFaultConstructor.subst(iop)
195    microopClasses["fault"] = Fault
196
197    class Halt(X86Microop):
198        className = "MicroHalt"
199        def __init__(self):
200            pass
201
202        def getAllocator(self, microFlags):
203            return "new MicroHalt(machInst, macrocodeBlock, %s)" % \
204                    self.microFlagsText(microFlags)
205
206    microopClasses["halt"] = Halt
207}};
208
209def template MicroFenceOpDeclare {{
210    class %(class_name)s : public X86ISA::X86MicroopBase
211    {
212      public:
213        %(class_name)s(ExtMachInst _machInst,
214                const char * instMnem,
215                uint64_t setFlags);
216
217        Fault execute(ExecContext *, Trace::InstRecord *) const;
218    };
219}};
220
221def template MicroFenceOpConstructor {{
222    %(class_name)s::%(class_name)s(
223            ExtMachInst machInst, const char * instMnem, uint64_t setFlags) :
224        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
225                setFlags, %(op_class)s)
226    {
227        %(constructor)s;
228    }
229}};
230
231let {{
232    class MfenceOp(X86Microop):
233        def __init__(self):
234            self.className = "Mfence"
235            self.mnemonic = "mfence"
236            self.instFlags = "| (1ULL << StaticInst::IsMemBarrier)"
237
238        def getAllocator(self, microFlags):
239            allocString = '''
240                    (StaticInstPtr)(new %(class_name)s(machInst,
241                        macrocodeBlock, %(flags)s))
242            '''
243            allocator = allocString % {
244                "class_name" : self.className,
245                "mnemonic" : self.mnemonic,
246                "flags" : self.microFlagsText(microFlags) + self.instFlags}
247            return allocator
248
249    microopClasses["mfence"] = MfenceOp
250}};
251
252let {{
253    # Build up the all register version of this micro op
254    iop = InstObjParams("mfence", "Mfence", 'X86MicroopBase',
255            {"code" : ""})
256    header_output += MicroFenceOpDeclare.subst(iop)
257    decoder_output += MicroFenceOpConstructor.subst(iop)
258    exec_output += BasicExecute.subst(iop)
259}};
260