regop.isa revision 4581:23166f771fa4
1// Copyright (c) 2007 The Hewlett-Packard Development Company
2// All rights reserved.
3//
4// Redistribution and use of this software in source and binary forms,
5// with or without modification, are permitted provided that the
6// following conditions are met:
7//
8// The software must be used only for Non-Commercial Use which means any
9// use which is NOT directed to receiving any direct monetary
10// compensation for, or commercial advantage from such use.  Illustrative
11// examples of non-commercial use are academic research, personal study,
12// teaching, education and corporate research & development.
13// Illustrative examples of commercial use are distributing products for
14// commercial advantage and providing services using the software for
15// commercial advantage.
16//
17// If you wish to use this software or functionality therein that may be
18// covered by patents for commercial use, please contact:
19//     Director of Intellectual Property Licensing
20//     Office of Strategy and Technology
21//     Hewlett-Packard Company
22//     1501 Page Mill Road
23//     Palo Alto, California  94304
24//
25// Redistributions of source code must retain the above copyright notice,
26// this list of conditions and the following disclaimer.  Redistributions
27// in binary form must reproduce the above copyright notice, this list of
28// conditions and the following disclaimer in the documentation and/or
29// other materials provided with the distribution.  Neither the name of
30// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
31// contributors may be used to endorse or promote products derived from
32// this software without specific prior written permission.  No right of
33// sublicense is granted herewith.  Derivatives of the software and
34// output created using the software may be prepared, but only for
35// Non-Commercial Uses.  Derivatives of the software may be shared with
36// others provided: (i) the others agree to abide by the list of
37// conditions herein which includes the Non-Commercial Use restrictions;
38// and (ii) such Derivatives of the software include the above copyright
39// notice to acknowledge the contribution from this software where
40// applicable, this list of conditions and the disclaimer below.
41//
42// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53//
54// Authors: Gabe Black
55
56//////////////////////////////////////////////////////////////////////////
57//
58// RegOp Microop templates
59//
60//////////////////////////////////////////////////////////////////////////
61
62output header {{
63    /**
64     * Base classes for RegOps which provides a generateDisassembly method.
65     */
66    class RegOp : public X86MicroopBase
67    {
68      protected:
69        const RegIndex src1;
70        const RegIndex src2;
71        const RegIndex dest;
72        const bool setStatus;
73        const uint8_t dataSize;
74        const uint8_t ext;
75
76        // Constructor
77        RegOp(ExtMachInst _machInst,
78                const char *mnem, const char *_instMnem,
79                bool isMicro, bool isDelayed,
80                bool isFirst, bool isLast,
81                RegIndex _src1, RegIndex _src2, RegIndex _dest,
82                bool _setStatus, uint8_t _dataSize, uint8_t _ext,
83                OpClass __opClass) :
84            X86MicroopBase(_machInst, mnem, _instMnem,
85                    isMicro, isDelayed, isFirst, isLast,
86                    __opClass),
87            src1(_src1), src2(_src2), dest(_dest),
88            setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
89        {
90        }
91
92        std::string generateDisassembly(Addr pc,
93            const SymbolTable *symtab) const;
94    };
95
96    class RegOpImm : public X86MicroopBase
97    {
98      protected:
99        const RegIndex src1;
100        const uint8_t imm8;
101        const RegIndex dest;
102        const bool setStatus;
103        const uint8_t dataSize;
104        const uint8_t ext;
105
106        // Constructor
107        RegOpImm(ExtMachInst _machInst,
108                const char * mnem, const char *_instMnem,
109                bool isMicro, bool isDelayed,
110                bool isFirst, bool isLast,
111                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
112                bool _setStatus, uint8_t _dataSize, uint8_t _ext,
113                OpClass __opClass) :
114            X86MicroopBase(_machInst, mnem, _instMnem,
115                    isMicro, isDelayed, isFirst, isLast,
116                    __opClass),
117            src1(_src1), imm8(_imm8), dest(_dest),
118            setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
119        {
120        }
121
122        std::string generateDisassembly(Addr pc,
123            const SymbolTable *symtab) const;
124    };
125}};
126
127output decoder {{
128    std::string RegOp::generateDisassembly(Addr pc,
129            const SymbolTable *symtab) const
130    {
131        std::stringstream response;
132
133        printMnemonic(response, instMnem, mnemonic);
134        printReg(response, dest);
135        response << ", ";
136        printReg(response, src1);
137        response << ", ";
138        printReg(response, src2);
139        return response.str();
140    }
141
142    std::string RegOpImm::generateDisassembly(Addr pc,
143            const SymbolTable *symtab) const
144    {
145        std::stringstream response;
146
147        printMnemonic(response, instMnem, mnemonic);
148        printReg(response, dest);
149        response << ", ";
150        printReg(response, src1);
151        ccprintf(response, ", %#x", imm8);
152        return response.str();
153    }
154}};
155
156def template MicroRegOpExecute {{
157        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
158                Trace::InstRecord *traceData) const
159        {
160            Fault fault = NoFault;
161
162            %(op_decl)s;
163            %(op_rd)s;
164            %(code)s;
165
166            //Write the resulting state to the execution context
167            if(fault == NoFault)
168            {
169                %(op_wb)s;
170            }
171            return fault;
172        }
173}};
174
175def template MicroRegOpImmExecute {{
176        Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc,
177                Trace::InstRecord *traceData) const
178        {
179            Fault fault = NoFault;
180
181            %(op_decl)s;
182            %(op_rd)s;
183            %(code)s;
184
185            //Write the resulting state to the execution context
186            if(fault == NoFault)
187            {
188                %(op_wb)s;
189            }
190            return fault;
191        }
192}};
193
194def template MicroRegOpDeclare {{
195    class %(class_name)s : public %(base_class)s
196    {
197      protected:
198        void buildMe();
199
200      public:
201        %(class_name)s(ExtMachInst _machInst,
202                const char * instMnem,
203                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
204                RegIndex _src1, RegIndex _src2, RegIndex _dest,
205                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
206
207        %(class_name)s(ExtMachInst _machInst,
208                const char * instMnem,
209                RegIndex _src1, RegIndex _src2, RegIndex _dest,
210                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
211
212        %(BasicExecDeclare)s
213    };
214}};
215
216def template MicroRegOpImmDeclare {{
217
218    class %(class_name)sImm : public %(base_class)s
219    {
220      protected:
221        void buildMe();
222
223      public:
224        %(class_name)sImm(ExtMachInst _machInst,
225                const char * instMnem,
226                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
227                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
228                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
229
230        %(class_name)sImm(ExtMachInst _machInst,
231                const char * instMnem,
232                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
233                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
234
235        %(BasicExecDeclare)s
236    };
237}};
238
239def template MicroRegOpConstructor {{
240
241    inline void %(class_name)s::buildMe()
242    {
243        %(constructor)s;
244    }
245
246    inline %(class_name)s::%(class_name)s(
247            ExtMachInst machInst, const char * instMnem,
248            RegIndex _src1, RegIndex _src2, RegIndex _dest,
249            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
250        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
251                false, false, false, false,
252                _src1, _src2, _dest, _setStatus, _dataSize, _ext,
253                %(op_class)s)
254    {
255        buildMe();
256    }
257
258    inline %(class_name)s::%(class_name)s(
259            ExtMachInst machInst, const char * instMnem,
260            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
261            RegIndex _src1, RegIndex _src2, RegIndex _dest,
262            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
263        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
264                isMicro, isDelayed, isFirst, isLast,
265                _src1, _src2, _dest, _setStatus, _dataSize, _ext,
266                %(op_class)s)
267    {
268        buildMe();
269    }
270}};
271
272def template MicroRegOpImmConstructor {{
273
274    inline void %(class_name)sImm::buildMe()
275    {
276        %(constructor)s;
277    }
278
279    inline %(class_name)sImm::%(class_name)sImm(
280            ExtMachInst machInst, const char * instMnem,
281            RegIndex _src1, uint8_t _imm8, RegIndex _dest,
282            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
283        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
284                false, false, false, false,
285                _src1, _imm8, _dest, _setStatus, _dataSize, _ext,
286                %(op_class)s)
287    {
288        buildMe();
289    }
290
291    inline %(class_name)sImm::%(class_name)sImm(
292            ExtMachInst machInst, const char * instMnem,
293            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
294            RegIndex _src1, uint8_t _imm8, RegIndex _dest,
295            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
296        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
297                isMicro, isDelayed, isFirst, isLast,
298                _src1, _imm8, _dest, _setStatus, _dataSize, _ext,
299                %(op_class)s)
300    {
301        buildMe();
302    }
303}};
304
305let {{
306    class RegOp(X86Microop):
307        def __init__(self, dest, src1, src2):
308            self.dest = dest
309            self.src1 = src1
310            self.src2 = src2
311            self.setStatus = False
312            self.dataSize = "env.dataSize"
313            self.ext = 0
314
315        def getAllocator(self, *microFlags):
316            allocator = '''new %(class_name)s(machInst, mnemonic
317                    %(flags)s, %(src1)s, %(src2)s, %(dest)s,
318                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
319                "class_name" : self.className,
320                "flags" : self.microFlagsText(microFlags),
321                "src1" : self.src1, "src2" : self.src2,
322                "dest" : self.dest,
323                "setStatus" : self.cppBool(self.setStatus),
324                "dataSize" : self.dataSize,
325                "ext" : self.ext}
326            return allocator
327
328    class RegOpImm(X86Microop):
329        def __init__(self, dest, src1, imm8):
330            self.dest = dest
331            self.src1 = src1
332            self.imm8 = imm8
333            self.setStatus = False
334            self.dataSize = "env.dataSize"
335            self.ext = 0
336
337        def getAllocator(self, *microFlags):
338            allocator = '''new %(class_name)s(machInst, mnemonic
339                    %(flags)s, %(src1)s, %(imm8)s, %(dest)s,
340                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
341                "class_name" : self.className,
342                "flags" : self.microFlagsText(microFlags),
343                "src1" : self.src1, "imm8" : self.imm8,
344                "dest" : self.dest,
345                "setStatus" : self.cppBool(self.setStatus),
346                "dataSize" : self.dataSize,
347                "ext" : self.ext}
348            return allocator
349}};
350
351let {{
352
353    # Make these empty strings so that concatenating onto
354    # them will always work.
355    header_output = ""
356    decoder_output = ""
357    exec_output = ""
358
359    def defineMicroRegOp(mnemonic, code):
360        global header_output
361        global decoder_output
362        global exec_output
363        global microopClasses
364        Name = mnemonic
365        name = mnemonic.lower()
366
367        # Find op2 in each of the instruction definitions. Create two versions
368        # of the code, one with an integer operand, and one with an immediate
369        # operand.
370        matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
371        regCode = matcher.sub("SrcReg2", code)
372        immCode = matcher.sub("imm8", code)
373
374        # Build up the all register version of this micro op
375        iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode})
376        header_output += MicroRegOpDeclare.subst(iop)
377        decoder_output += MicroRegOpConstructor.subst(iop)
378        exec_output += MicroRegOpExecute.subst(iop)
379
380        class RegOpChild(RegOp):
381            def __init__(self, dest, src1, src2):
382                super(RegOpChild, self).__init__(dest, src1, src2)
383                self.className = Name
384                self.mnemonic = name
385
386        microopClasses[name] = RegOpChild
387
388        # Build up the immediate version of this micro op
389        iop = InstObjParams(name + "i", Name,
390                'RegOpImm', {"code" : immCode})
391        header_output += MicroRegOpImmDeclare.subst(iop)
392        decoder_output += MicroRegOpImmConstructor.subst(iop)
393        exec_output += MicroRegOpImmExecute.subst(iop)
394
395        class RegOpImmChild(RegOpImm):
396            def __init__(self, dest, src1, imm):
397                super(RegOpImmChild, self).__init__(dest, src1, imm)
398                self.className = Name + "Imm"
399                self.mnemonic = name + "i"
400
401        microopClasses[name + "i"] = RegOpImmChild
402
403    defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF
404    defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)')
405    defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to add in CF, set OF,CF,SF
406    defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to subtract CF, set OF,CF,SF
407    defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)')
408    defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to set OF,CF,SF
409    defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)')
410    defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg
411    defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)')
412
413}};
414