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