specop.isa revision 10341
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        %(BasicExecDeclare)s
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        %(BasicExecDeclare)s
87    };
88}};
89
90def template MicroFaultExecute {{
91        Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *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(CPU_EXEC_CONTEXT *xc,
108            Trace::InstRecord * traceData) const
109    {
110        xc->tcBase()->suspend();
111        return NoFault;
112    }
113}};
114
115output decoder {{
116    MicroFaultBase::MicroFaultBase(
117            ExtMachInst machInst, const char * instMnem,
118            uint64_t setFlags, Fault _fault, uint8_t _cc) :
119        X86MicroopBase(machInst, "fault", instMnem, setFlags, No_OpClass),
120                fault(_fault), cc(_cc)
121    {
122    }
123}};
124
125def template MicroFaultConstructor {{
126    %(class_name)s::%(class_name)s(
127            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
128            Fault _fault, uint8_t _cc) :
129        %(base_class)s(machInst, instMnem, setFlags, _fault, _cc)
130    {
131        %(constructor)s;
132    }
133}};
134
135output decoder {{
136    std::string MicroFaultBase::generateDisassembly(Addr pc,
137            const SymbolTable *symtab) const
138    {
139        std::stringstream response;
140
141        printMnemonic(response, instMnem, mnemonic);
142        if(fault)
143            response << fault->name();
144        else
145            response << "No Fault";
146
147        return response.str();
148    }
149
150    std::string MicroHalt::generateDisassembly(Addr pc,
151            const SymbolTable *symtab) const
152    {
153        std::stringstream response;
154
155        printMnemonic(response, instMnem, mnemonic);
156
157        return response.str();
158    }
159}};
160
161let {{
162    class Fault(X86Microop):
163        className = "MicroFault"
164        def __init__(self, fault, flags=None):
165            self.fault = fault
166            if flags:
167                if not isinstance(flags, (list, tuple)):
168                    raise Exception, "flags must be a list or tuple of flags"
169                self.cond = " | ".join(flags)
170                self.className += "Flags"
171            else:
172                self.cond = "0"
173
174        def getAllocator(self, microFlags):
175            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
176                    %(flags)s, %(fault)s, %(cc)s)''' % {
177                "class_name" : self.className,
178                "flags" : self.microFlagsText(microFlags),
179                "fault" : self.fault,
180                "cc" : self.cond}
181            return allocator
182
183    iop = InstObjParams("fault", "MicroFaultFlags", "MicroFaultBase",
184            {"code": "",
185             "cond_test": "checkCondition(ccFlagBits | cfofBits | dfBit | \
186                                          ecfBit | ezfBit, cc)"})
187    exec_output = MicroFaultExecute.subst(iop)
188    header_output = MicroFaultDeclare.subst(iop)
189    decoder_output = MicroFaultConstructor.subst(iop)
190    iop = InstObjParams("fault", "MicroFault", "MicroFaultBase",
191            {"code": "",
192             "cond_test": "true"})
193    exec_output += MicroFaultExecute.subst(iop)
194    header_output += MicroFaultDeclare.subst(iop)
195    decoder_output += MicroFaultConstructor.subst(iop)
196    microopClasses["fault"] = Fault
197
198    class Halt(X86Microop):
199        className = "MicroHalt"
200        def __init__(self):
201            pass
202
203        def getAllocator(self, microFlags):
204            return "new MicroHalt(machInst, macrocodeBlock, %s)" % \
205                    self.microFlagsText(microFlags)
206
207    microopClasses["halt"] = Halt
208}};
209
210def template MicroFenceOpDeclare {{
211    class %(class_name)s : public X86ISA::X86MicroopBase
212    {
213      public:
214        %(class_name)s(ExtMachInst _machInst,
215                const char * instMnem,
216                uint64_t setFlags);
217
218        %(BasicExecDeclare)s
219    };
220}};
221
222def template MicroFenceOpConstructor {{
223    %(class_name)s::%(class_name)s(
224            ExtMachInst machInst, const char * instMnem, uint64_t setFlags) :
225        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
226                setFlags, %(op_class)s)
227    {
228        %(constructor)s;
229    }
230}};
231
232let {{
233    class MfenceOp(X86Microop):
234        def __init__(self):
235            self.className = "Mfence"
236            self.mnemonic = "mfence"
237            self.instFlags = "| (1ULL << StaticInst::IsMemBarrier)"
238
239        def getAllocator(self, microFlags):
240            allocString = '''
241                    (StaticInstPtr)(new %(class_name)s(machInst,
242                        macrocodeBlock, %(flags)s))
243            '''
244            allocator = allocString % {
245                "class_name" : self.className,
246                "mnemonic" : self.mnemonic,
247                "flags" : self.microFlagsText(microFlags) + self.instFlags}
248            return allocator
249
250    microopClasses["mfence"] = MfenceOp
251}};
252
253let {{
254    # Build up the all register version of this micro op
255    iop = InstObjParams("mfence", "Mfence", 'X86MicroopBase',
256            {"code" : ""})
257    header_output += MicroFenceOpDeclare.subst(iop)
258    decoder_output += MicroFenceOpConstructor.subst(iop)
259    exec_output += BasicExecute.subst(iop)
260}};
261