ldstop.isa revision 4601:38c989d15fef
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// LdStOp Microop templates
59//
60//////////////////////////////////////////////////////////////////////////
61
62output header {{
63    /**
64     * Base class for load and store ops
65     */
66    class LdStOp : public X86MicroopBase
67    {
68      protected:
69        const uint8_t scale;
70        const RegIndex index;
71        const RegIndex base;
72        const uint64_t disp;
73        const uint8_t segment;
74        const RegIndex data;
75        const uint8_t dataSize;
76        const uint8_t addressSize;
77
78        //Constructor
79        LdStOp(ExtMachInst _machInst,
80                const char * mnem, const char * _instMnem,
81                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
82                uint8_t _scale, RegIndex _index, RegIndex _base,
83                uint64_t _disp, uint8_t _segment,
84                RegIndex _data,
85                uint8_t _dataSize, uint8_t _addressSize,
86                OpClass __opClass) :
87        X86MicroopBase(machInst, mnem, _instMnem,
88                isMicro, isDelayed, isFirst, isLast, __opClass),
89                scale(_scale), index(_index), base(_base),
90                disp(_disp), segment(_segment),
91                data(_data),
92                dataSize(_dataSize), addressSize(_addressSize)
93        {}
94
95        std::string generateDisassembly(Addr pc,
96            const SymbolTable *symtab) const;
97    };
98}};
99
100output decoder {{
101    std::string LdStOp::generateDisassembly(Addr pc,
102            const SymbolTable *symtab) const
103    {
104        std::stringstream response;
105
106        printMnemonic(response, instMnem, mnemonic);
107        printReg(response, data);
108        response << ", ";
109        printSegment(response, segment);
110        ccprintf(response, ":[%d*", scale);
111        printReg(response, index);
112        response << " + ";
113        printReg(response, base);
114        ccprintf(response, " + %#x]", disp);
115        return response.str();
116    }
117}};
118
119// LEA template
120
121def template MicroLeaExecute {{
122    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
123          Trace::InstRecord *traceData) const
124    {
125        Fault fault = NoFault;
126        Addr EA;
127
128        %(op_decl)s;
129        %(op_rd)s;
130        %(ea_code)s;
131        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
132
133        %(code)s;
134        if(fault == NoFault)
135        {
136            %(op_wb)s;
137        }
138
139        return fault;
140    }
141}};
142
143def template MicroLeaDeclare {{
144    class %(class_name)s : public %(base_class)s
145    {
146      protected:
147        void buildMe();
148
149      public:
150        %(class_name)s(ExtMachInst _machInst,
151                const char * instMnem,
152                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
153                uint8_t _scale, RegIndex _index, RegIndex _base,
154                uint64_t _disp, uint8_t _segment,
155                RegIndex _data,
156                uint8_t _dataSize, uint8_t _addressSize);
157
158        %(class_name)s(ExtMachInst _machInst,
159                const char * instMnem,
160                uint8_t _scale, RegIndex _index, RegIndex _base,
161                uint64_t _disp, uint8_t _segment,
162                RegIndex _data,
163                uint8_t _dataSize, uint8_t _addressSize);
164
165        %(BasicExecDeclare)s
166    };
167}};
168
169// Load templates
170
171def template MicroLoadExecute {{
172    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
173          Trace::InstRecord *traceData) const
174    {
175        Fault fault = NoFault;
176        Addr EA;
177
178        %(op_decl)s;
179        %(op_rd)s;
180        %(ea_code)s;
181        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
182
183        fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
184        if(fault == NoFault)
185        {
186            %(code)s;
187        }
188        if(fault == NoFault)
189        {
190            %(op_wb)s;
191        }
192
193        return fault;
194    }
195}};
196
197def template MicroLoadInitiateAcc {{
198    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
199            Trace::InstRecord * traceData) const
200    {
201        Fault fault = NoFault;
202        Addr EA;
203
204        %(op_decl)s;
205        %(op_rd)s;
206        %(ea_code)s;
207        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
208
209        fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
210
211        return fault;
212    }
213}};
214
215def template MicroLoadCompleteAcc {{
216    Fault %(class_name)s::completeAcc(PacketPtr pkt,
217            %(CPU_exec_context)s * xc,
218            Trace::InstRecord * traceData) const
219    {
220        Fault fault = NoFault;
221
222        %(op_decl)s;
223        %(op_rd)s;
224
225        Mem = pkt->get<typeof(Mem)>();
226        %(code)s;
227
228        if(fault == NoFault)
229        {
230            %(op_wb)s;
231        }
232
233        return fault;
234    }
235}};
236
237// Store templates
238
239def template MicroStoreExecute {{
240    Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
241            Trace::InstRecord *traceData) const
242    {
243        Fault fault = NoFault;
244
245        Addr EA;
246        %(op_decl)s;
247        %(op_rd)s;
248        %(ea_code)s;
249        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
250
251        %(code)s;
252
253        if(fault == NoFault)
254        {
255            fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
256                    EA, 0, 0);
257        }
258        if(fault == NoFault)
259        {
260            %(op_wb)s;
261        }
262
263        return fault;
264    }
265}};
266
267def template MicroStoreInitiateAcc {{
268    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
269            Trace::InstRecord * traceData) const
270    {
271        Fault fault = NoFault;
272
273        Addr EA;
274        %(op_decl)s;
275        %(op_rd)s;
276        %(ea_code)s;
277        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
278
279        %(code)s;
280
281        if(fault == NoFault)
282        {
283            fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
284                    EA, 0, 0);
285        }
286        if(fault == NoFault)
287        {
288            %(op_wb)s;
289        }
290        return fault;
291    }
292}};
293
294def template MicroStoreCompleteAcc {{
295    Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
296            Trace::InstRecord * traceData) const
297    {
298        return NoFault;
299    }
300}};
301
302// Common templates
303
304//This delcares the initiateAcc function in memory operations
305def template InitiateAccDeclare {{
306    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
307}};
308
309//This declares the completeAcc function in memory operations
310def template CompleteAccDeclare {{
311    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
312}};
313
314def template MicroLdStOpDeclare {{
315    class %(class_name)s : public %(base_class)s
316    {
317      protected:
318        void buildMe();
319
320      public:
321        %(class_name)s(ExtMachInst _machInst,
322                const char * instMnem,
323                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
324                uint8_t _scale, RegIndex _index, RegIndex _base,
325                uint64_t _disp, uint8_t _segment,
326                RegIndex _data,
327                uint8_t _dataSize, uint8_t _addressSize);
328
329        %(class_name)s(ExtMachInst _machInst,
330                const char * instMnem,
331                uint8_t _scale, RegIndex _index, RegIndex _base,
332                uint64_t _disp, uint8_t _segment,
333                RegIndex _data,
334                uint8_t _dataSize, uint8_t _addressSize);
335
336        %(BasicExecDeclare)s
337
338        %(InitiateAccDeclare)s
339
340        %(CompleteAccDeclare)s
341    };
342}};
343
344def template MicroLdStOpConstructor {{
345
346    inline void %(class_name)s::buildMe()
347    {
348        %(constructor)s;
349    }
350
351    inline %(class_name)s::%(class_name)s(
352            ExtMachInst machInst, const char * instMnem,
353            uint8_t _scale, RegIndex _index, RegIndex _base,
354            uint64_t _disp, uint8_t _segment,
355            RegIndex _data,
356            uint8_t _dataSize, uint8_t _addressSize) :
357        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
358                false, false, false, false,
359                _scale, _index, _base,
360                _disp, _segment, _data,
361                _dataSize, _addressSize, %(op_class)s)
362    {
363        buildMe();
364    }
365
366    inline %(class_name)s::%(class_name)s(
367            ExtMachInst machInst, const char * instMnem,
368            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
369            uint8_t _scale, RegIndex _index, RegIndex _base,
370            uint64_t _disp, uint8_t _segment,
371            RegIndex _data,
372            uint8_t _dataSize, uint8_t _addressSize) :
373        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
374                isMicro, isDelayed, isFirst, isLast,
375                _scale, _index, _base,
376                _disp, _segment, _data,
377                _dataSize, _addressSize, %(op_class)s)
378    {
379        buildMe();
380    }
381}};
382
383let {{
384    class LdStOp(X86Microop):
385        def __init__(self, data, segment, addr, disp):
386            self.data = data
387            [self.scale, self.index, self.base] = addr
388            self.disp = disp
389            self.segment = segment
390            self.dataSize = "env.dataSize"
391            self.addressSize = "env.addressSize"
392
393        def getAllocator(self, *microFlags):
394            allocator = '''new %(class_name)s(machInst, mnemonic
395                    %(flags)s, %(scale)s, %(index)s, %(base)s,
396                    %(disp)s, %(segment)s, %(data)s,
397                    %(dataSize)s, %(addressSize)s)''' % {
398                "class_name" : self.className,
399                "flags" : self.microFlagsText(microFlags),
400                "scale" : self.scale, "index" : self.index,
401                "base" : self.base,
402                "disp" : self.disp,
403                "segment" : self.segment, "data" : self.data,
404                "dataSize" : self.dataSize, "addressSize" : self.addressSize}
405            return allocator
406}};
407
408let {{
409
410    # Make these empty strings so that concatenating onto
411    # them will always work.
412    header_output = ""
413    decoder_output = ""
414    exec_output = ""
415
416    calculateEA = "EA = scale * Index + Base + disp;"
417
418    def defineMicroLoadOp(mnemonic, code):
419        global header_output
420        global decoder_output
421        global exec_output
422        global microopClasses
423        Name = mnemonic
424        name = mnemonic.lower()
425
426        # Build up the all register version of this micro op
427        iop = InstObjParams(name, Name, 'LdStOp',
428                {"code": code, "ea_code": calculateEA})
429        header_output += MicroLdStOpDeclare.subst(iop)
430        decoder_output += MicroLdStOpConstructor.subst(iop)
431        exec_output += MicroLoadExecute.subst(iop)
432        exec_output += MicroLoadInitiateAcc.subst(iop)
433        exec_output += MicroLoadCompleteAcc.subst(iop)
434
435        class LoadOp(LdStOp):
436            def __init__(self, data, segment, addr, disp = 0):
437                super(LoadOp, self).__init__(data, segment, addr, disp)
438                self.className = Name
439                self.mnemonic = name
440
441        microopClasses[name] = LoadOp
442
443    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
444
445    def defineMicroStoreOp(mnemonic, code):
446        global header_output
447        global decoder_output
448        global exec_output
449        global microopClasses
450        Name = mnemonic
451        name = mnemonic.lower()
452
453        # Build up the all register version of this micro op
454        iop = InstObjParams(name, Name, 'LdStOp',
455                {"code": code, "ea_code": calculateEA})
456        header_output += MicroLdStOpDeclare.subst(iop)
457        decoder_output += MicroLdStOpConstructor.subst(iop)
458        exec_output += MicroStoreExecute.subst(iop)
459        exec_output += MicroStoreInitiateAcc.subst(iop)
460        exec_output += MicroStoreCompleteAcc.subst(iop)
461
462        class StoreOp(LdStOp):
463            def __init__(self, data, segment, addr, disp = 0):
464                super(LoadOp, self).__init__(data, segment, addr, disp)
465                self.className = Name
466                self.mnemonic = name
467
468        microopClasses[name] = StoreOp
469
470    defineMicroLoadOp('St', 'Mem = Data;')
471
472    iop = InstObjParams("lea", "Lea", 'LdStOp',
473            {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA})
474    header_output += MicroLeaDeclare.subst(iop)
475    decoder_output += MicroLdStOpConstructor.subst(iop)
476    exec_output += MicroLeaExecute.subst(iop)
477
478    class LeaOp(LdStOp):
479        def __init__(self, data, segment, addr, disp = 0):
480            super(LeaOp, self).__init__(data, segment, addr, disp)
481            self.className = "Lea"
482            self.mnemonic = "lea"
483
484    microopClasses["lea"] = LeaOp
485}};
486
487