specop.isa revision 10196
1247Sstever@eecs.umich.edu// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
21372Sstever@eecs.umich.edu// Copyright (c) 2011 Mark D. Hill and David A. Wood
3247Sstever@eecs.umich.edu// All rights reserved.
4247Sstever@eecs.umich.edu//
5247Sstever@eecs.umich.edu// The license below extends only to copyright in the software and shall
6247Sstever@eecs.umich.edu// not be construed as granting a license to any other intellectual
7247Sstever@eecs.umich.edu// property including but not limited to intellectual property relating
8247Sstever@eecs.umich.edu// to a hardware implementation of the functionality of the software
9247Sstever@eecs.umich.edu// licensed hereunder.  You may use the software subject to the license
10247Sstever@eecs.umich.edu// terms below provided that you ensure that this notice is replicated
11247Sstever@eecs.umich.edu// unmodified and in its entirety in all distributions of the software,
12247Sstever@eecs.umich.edu// modified or unmodified, in source code or in binary form.
13247Sstever@eecs.umich.edu//
14247Sstever@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
15247Sstever@eecs.umich.edu// modification, are permitted provided that the following conditions are
16247Sstever@eecs.umich.edu// met: redistributions of source code must retain the above copyright
17247Sstever@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
18247Sstever@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
19247Sstever@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
20247Sstever@eecs.umich.edu// documentation and/or other materials provided with the distribution;
21247Sstever@eecs.umich.edu// neither the name of the copyright holders nor the names of its
22247Sstever@eecs.umich.edu// contributors may be used to endorse or promote products derived from
23247Sstever@eecs.umich.edu// this software without specific prior written permission.
24247Sstever@eecs.umich.edu//
25247Sstever@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26247Sstever@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27247Sstever@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28247Sstever@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29247Sstever@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
301123Sstever@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
311123Sstever@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
321123Sstever@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
331123Sstever@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
341123Sstever@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
351123Sstever@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
361123Sstever@eecs.umich.edu//
371123Sstever@eecs.umich.edu// Authors: Gabe Black
381123Sstever@eecs.umich.edu
391123Sstever@eecs.umich.edu//////////////////////////////////////////////////////////////////////////
401123Sstever@eecs.umich.edu//
41247Sstever@eecs.umich.edu// Fault Microop
42247Sstever@eecs.umich.edu//
431123Sstever@eecs.umich.edu//////////////////////////////////////////////////////////////////////////
44247Sstever@eecs.umich.edu
45247Sstever@eecs.umich.eduoutput header {{
46247Sstever@eecs.umich.edu    class MicroFaultBase : public X86ISA::X86MicroopBase
47247Sstever@eecs.umich.edu    {
48247Sstever@eecs.umich.edu      protected:
49247Sstever@eecs.umich.edu        Fault fault;
50247Sstever@eecs.umich.edu        uint8_t cc;
51247Sstever@eecs.umich.edu
52579Sstever@eecs.umich.edu      public:
53247Sstever@eecs.umich.edu        MicroFaultBase(ExtMachInst _machInst, const char * instMnem,
541123Sstever@eecs.umich.edu                uint64_t setFlags, Fault _fault, uint8_t _cc);
551123Sstever@eecs.umich.edu
561372Sstever@eecs.umich.edu        std::string generateDisassembly(Addr pc,
571123Sstever@eecs.umich.edu                const SymbolTable *symtab) const;
58704Sstever@eecs.umich.edu    };
59704Sstever@eecs.umich.edu
60247Sstever@eecs.umich.edu    class MicroHalt : public X86ISA::X86MicroopBase
61247Sstever@eecs.umich.edu    {
62247Sstever@eecs.umich.edu      public:
63247Sstever@eecs.umich.edu        MicroHalt(ExtMachInst _machInst, const char * instMnem,
64247Sstever@eecs.umich.edu                uint64_t setFlags) :
65247Sstever@eecs.umich.edu            X86MicroopBase(_machInst, "halt", instMnem,
66247Sstever@eecs.umich.edu                           setFlags | (ULL(1) << StaticInst::IsNonSpeculative),
67247Sstever@eecs.umich.edu                           No_OpClass)
68247Sstever@eecs.umich.edu        {
69247Sstever@eecs.umich.edu        }
70
71        %(BasicExecDeclare)s
72
73        std::string generateDisassembly(Addr pc,
74                const SymbolTable *symtab) const;
75    };
76}};
77
78def template MicroFaultDeclare {{
79    class %(class_name)s : public %(base_class)s
80    {
81      public:
82        %(class_name)s(ExtMachInst _machInst, const char * instMnem,
83                uint64_t setFlags, Fault _fault, uint8_t _cc);
84
85        %(BasicExecDeclare)s
86    };
87}};
88
89def template MicroFaultExecute {{
90        Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
91                Trace::InstRecord *traceData) const
92        {
93            %(op_decl)s;
94            %(op_rd)s;
95            if (%(cond_test)s) {
96                //Return the fault we were constructed with
97                return fault;
98            } else {
99                return NoFault;
100            }
101        }
102}};
103
104output exec {{
105    Fault
106    MicroHalt::execute(CPU_EXEC_CONTEXT *xc,
107            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        %(BasicExecDeclare)s
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