regop.isa revision 4612:a29c0616839d
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            %(flag_code)s;
166
167            //Write the resulting state to the execution context
168            if(fault == NoFault)
169            {
170                %(op_wb)s;
171            }
172            return fault;
173        }
174}};
175
176def template MicroRegOpImmExecute {{
177        Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc,
178                Trace::InstRecord *traceData) const
179        {
180            Fault fault = NoFault;
181
182            %(op_decl)s;
183            %(op_rd)s;
184            %(code)s;
185            %(flag_code)s;
186
187            //Write the resulting state to the execution context
188            if(fault == NoFault)
189            {
190                %(op_wb)s;
191            }
192            return fault;
193        }
194}};
195
196def template MicroRegOpDeclare {{
197    class %(class_name)s : public %(base_class)s
198    {
199      protected:
200        void buildMe();
201
202      public:
203        %(class_name)s(ExtMachInst _machInst,
204                const char * instMnem,
205                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
206                RegIndex _src1, RegIndex _src2, RegIndex _dest,
207                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
208
209        %(class_name)s(ExtMachInst _machInst,
210                const char * instMnem,
211                RegIndex _src1, RegIndex _src2, RegIndex _dest,
212                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
213
214        %(BasicExecDeclare)s
215    };
216}};
217
218def template MicroRegOpImmDeclare {{
219
220    class %(class_name)sImm : public %(base_class)s
221    {
222      protected:
223        void buildMe();
224
225      public:
226        %(class_name)sImm(ExtMachInst _machInst,
227                const char * instMnem,
228                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
229                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
230                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
231
232        %(class_name)sImm(ExtMachInst _machInst,
233                const char * instMnem,
234                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
235                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
236
237        %(BasicExecDeclare)s
238    };
239}};
240
241def template MicroRegOpConstructor {{
242
243    inline void %(class_name)s::buildMe()
244    {
245        %(constructor)s;
246    }
247
248    inline %(class_name)s::%(class_name)s(
249            ExtMachInst machInst, const char * instMnem,
250            RegIndex _src1, RegIndex _src2, RegIndex _dest,
251            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
252        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
253                false, false, false, false,
254                _src1, _src2, _dest, _setStatus, _dataSize, _ext,
255                %(op_class)s)
256    {
257        buildMe();
258    }
259
260    inline %(class_name)s::%(class_name)s(
261            ExtMachInst machInst, const char * instMnem,
262            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
263            RegIndex _src1, RegIndex _src2, RegIndex _dest,
264            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
265        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
266                isMicro, isDelayed, isFirst, isLast,
267                _src1, _src2, _dest, _setStatus, _dataSize, _ext,
268                %(op_class)s)
269    {
270        buildMe();
271    }
272}};
273
274def template MicroRegOpImmConstructor {{
275
276    inline void %(class_name)sImm::buildMe()
277    {
278        %(constructor)s;
279    }
280
281    inline %(class_name)sImm::%(class_name)sImm(
282            ExtMachInst machInst, const char * instMnem,
283            RegIndex _src1, uint8_t _imm8, RegIndex _dest,
284            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
285        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
286                false, false, false, false,
287                _src1, _imm8, _dest, _setStatus, _dataSize, _ext,
288                %(op_class)s)
289    {
290        buildMe();
291    }
292
293    inline %(class_name)sImm::%(class_name)sImm(
294            ExtMachInst machInst, const char * instMnem,
295            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
296            RegIndex _src1, uint8_t _imm8, RegIndex _dest,
297            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
298        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
299                isMicro, isDelayed, isFirst, isLast,
300                _src1, _imm8, _dest, _setStatus, _dataSize, _ext,
301                %(op_class)s)
302    {
303        buildMe();
304    }
305}};
306
307let {{
308    class RegOp(X86Microop):
309        def __init__(self, dest, src1, src2, setStatus):
310            self.dest = dest
311            self.src1 = src1
312            self.src2 = src2
313            self.setStatus = setStatus
314            self.dataSize = "env.dataSize"
315            self.ext = 0
316
317        def getAllocator(self, *microFlags):
318            allocator = '''new %(class_name)s(machInst, mnemonic
319                    %(flags)s, %(src1)s, %(src2)s, %(dest)s,
320                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
321                "class_name" : self.className,
322                "flags" : self.microFlagsText(microFlags),
323                "src1" : self.src1, "src2" : self.src2,
324                "dest" : self.dest,
325                "setStatus" : self.cppBool(self.setStatus),
326                "dataSize" : self.dataSize,
327                "ext" : self.ext}
328            return allocator
329
330    class RegOpImm(X86Microop):
331        def __init__(self, dest, src1, imm8, setStatus):
332            self.dest = dest
333            self.src1 = src1
334            self.imm8 = imm8
335            self.setStatus = setStatus
336            self.dataSize = "env.dataSize"
337            self.ext = 0
338
339        def getAllocator(self, *microFlags):
340            allocator = '''new %(class_name)s(machInst, mnemonic
341                    %(flags)s, %(src1)s, %(imm8)s, %(dest)s,
342                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
343                "class_name" : self.className,
344                "flags" : self.microFlagsText(microFlags),
345                "src1" : self.src1, "imm8" : self.imm8,
346                "dest" : self.dest,
347                "setStatus" : self.cppBool(self.setStatus),
348                "dataSize" : self.dataSize,
349                "ext" : self.ext}
350            return allocator
351}};
352
353let {{
354
355    # Make these empty strings so that concatenating onto
356    # them will always work.
357    header_output = ""
358    decoder_output = ""
359    exec_output = ""
360
361    def setUpMicroRegOp(name, Name, base, code, child, flagCode):
362        global header_output
363        global decoder_output
364        global exec_output
365        global microopClasses
366
367        iop = InstObjParams(name, Name, base,
368                {"code" : code,
369                 "flag_code" : flagCode})
370        header_output += MicroRegOpDeclare.subst(iop)
371        decoder_output += MicroRegOpConstructor.subst(iop)
372        exec_output += MicroRegOpExecute.subst(iop)
373
374        microopClasses[name] = child
375
376    def defineMicroRegOp(mnemonic, code, flagCode):
377        Name = mnemonic
378        name = mnemonic.lower()
379
380        # Find op2 in each of the instruction definitions. Create two versions
381        # of the code, one with an integer operand, and one with an immediate
382        # operand.
383        matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
384        regCode = matcher.sub("SrcReg2", code)
385        immCode = matcher.sub("imm8", code)
386
387        # Build the all register version of this micro op
388        class RegOpChild(RegOp):
389            def __init__(self, dest, src1, src2, setStatus=False):
390                super(RegOpChild, self).__init__(dest, src1, src2, setStatus)
391                self.className = Name
392                self.mnemonic = name
393
394        setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, flagCode);
395
396        # Build the immediate version of this micro op
397        class RegOpChildImm(RegOpImm):
398            def __init__(self, dest, src1, src2, setStatus=False):
399                super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus)
400                self.className = Name + "Imm"
401                self.mnemonic = name + "i"
402
403        setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, flagCode);
404
405    defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF
406    defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "")
407    defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF
408    defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF
409    defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "")
410    defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF
411    defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "")
412    defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg
413    defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "")
414
415    # This has it's own function because Wr ops have implicit destinations
416    def defineMicroRegOpWr(mnemonic, code):
417        Name = mnemonic
418        name = mnemonic.lower()
419
420        # Find op2 in each of the instruction definitions. Create two versions
421        # of the code, one with an integer operand, and one with an immediate
422        # operand.
423        matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
424        regCode = matcher.sub("SrcReg2", code)
425        immCode = matcher.sub("imm8", code)
426
427        # Build the all register version of this micro op
428        class RegOpChild(RegOp):
429            def __init__(self, src1, src2):
430                super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False)
431                self.className = Name
432                self.mnemonic = name
433
434        setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, "");
435
436        # Build the immediate version of this micro op
437        class RegOpChildImm(RegOpImm):
438            def __init__(self, src1, src2):
439                super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False)
440                self.className = Name + "Imm"
441                self.mnemonic = name + "i"
442
443        setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, "");
444
445    defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2')
446
447    # This has it's own function because Rd ops don't always have two parameters
448    def defineMicroRegOpRd(mnemonic, code):
449        Name = mnemonic
450        name = mnemonic.lower()
451
452        class RegOpChild(RegOp):
453            def __init__(self, dest, src1 = "NUM_INTREGS"):
454                super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False)
455                self.className = Name
456                self.mnemonic = name
457
458        setUpMicroRegOp(name, Name, "RegOp", code, RegOpChild, "");
459
460    defineMicroRegOpRd('Rdip', 'DestReg = RIP')
461
462    def defineMicroRegOpImm(mnemonic, code):
463        Name = mnemonic
464        name = mnemonic.lower()
465
466        class RegOpChild(RegOpImm):
467            def __init__(self, dest, src1, src2):
468                super(RegOpChild, self).__init__(dest, src1, src2, False)
469                self.className = Name
470                self.mnemonic = name
471
472        setUpMicroRegOp(name, Name, "RegOpImm", code, RegOpChild, "");
473
474    defineMicroRegOpImm('Sext', '''
475            IntReg val = SrcReg1;
476            int sign_bit = bits(val, imm8-1, imm8-1);
477            val = sign_bit ? (val | ~mask(imm8)) : val;
478            DestReg = merge(DestReg, val, dataSize);''')
479}};
480