ldstop.isa revision 5359:8c6ff200e4c1
1// Copyright (c) 2008 The Regents of The University of Michigan
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met: redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer;
8// redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution;
11// neither the name of the copyright holders nor the names of its
12// contributors may be used to endorse or promote products derived from
13// this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26//
27// Authors: Gabe Black
28
29// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
30// All rights reserved.
31//
32// Redistribution and use of this software in source and binary forms,
33// with or without modification, are permitted provided that the
34// following conditions are met:
35//
36// The software must be used only for Non-Commercial Use which means any
37// use which is NOT directed to receiving any direct monetary
38// compensation for, or commercial advantage from such use.  Illustrative
39// examples of non-commercial use are academic research, personal study,
40// teaching, education and corporate research & development.
41// Illustrative examples of commercial use are distributing products for
42// commercial advantage and providing services using the software for
43// commercial advantage.
44//
45// If you wish to use this software or functionality therein that may be
46// covered by patents for commercial use, please contact:
47//     Director of Intellectual Property Licensing
48//     Office of Strategy and Technology
49//     Hewlett-Packard Company
50//     1501 Page Mill Road
51//     Palo Alto, California  94304
52//
53// Redistributions of source code must retain the above copyright notice,
54// this list of conditions and the following disclaimer.  Redistributions
55// in binary form must reproduce the above copyright notice, this list of
56// conditions and the following disclaimer in the documentation and/or
57// other materials provided with the distribution.  Neither the name of
58// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
59// contributors may be used to endorse or promote products derived from
60// this software without specific prior written permission.  No right of
61// sublicense is granted herewith.  Derivatives of the software and
62// output created using the software may be prepared, but only for
63// Non-Commercial Uses.  Derivatives of the software may be shared with
64// others provided: (i) the others agree to abide by the list of
65// conditions herein which includes the Non-Commercial Use restrictions;
66// and (ii) such Derivatives of the software include the above copyright
67// notice to acknowledge the contribution from this software where
68// applicable, this list of conditions and the disclaimer below.
69//
70// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
71// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
72// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
73// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
74// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
75// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
76// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
77// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
78// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
79// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81//
82// Authors: Gabe Black
83
84//////////////////////////////////////////////////////////////////////////
85//
86// LdStOp Microop templates
87//
88//////////////////////////////////////////////////////////////////////////
89
90// LEA template
91
92def template MicroLeaExecute {{
93    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
94          Trace::InstRecord *traceData) const
95    {
96        Fault fault = NoFault;
97        Addr EA;
98
99        %(op_decl)s;
100        %(op_rd)s;
101        %(ea_code)s;
102        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
103
104        %(code)s;
105        if(fault == NoFault)
106        {
107            %(op_wb)s;
108        }
109
110        return fault;
111    }
112}};
113
114def template MicroLeaDeclare {{
115    class %(class_name)s : public %(base_class)s
116    {
117      protected:
118        void buildMe();
119
120      public:
121        %(class_name)s(ExtMachInst _machInst,
122                const char * instMnem,
123                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
124                uint8_t _scale, RegIndex _index, RegIndex _base,
125                uint64_t _disp, uint8_t _segment,
126                RegIndex _data,
127                uint8_t _dataSize, uint8_t _addressSize);
128
129        %(class_name)s(ExtMachInst _machInst,
130                const char * instMnem,
131                uint8_t _scale, RegIndex _index, RegIndex _base,
132                uint64_t _disp, uint8_t _segment,
133                RegIndex _data,
134                uint8_t _dataSize, uint8_t _addressSize);
135
136        %(BasicExecDeclare)s
137    };
138}};
139
140// Load templates
141
142def template MicroLoadExecute {{
143    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
144          Trace::InstRecord *traceData) const
145    {
146        Fault fault = NoFault;
147        Addr EA;
148
149        %(op_decl)s;
150        %(op_rd)s;
151        %(ea_code)s;
152        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
153
154        fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
155
156        if(fault == NoFault)
157        {
158            %(code)s;
159        }
160        if(fault == NoFault)
161        {
162            %(op_wb)s;
163        }
164
165        return fault;
166    }
167}};
168
169def template MicroLoadInitiateAcc {{
170    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
171            Trace::InstRecord * traceData) const
172    {
173        Fault fault = NoFault;
174        Addr EA;
175
176        %(op_decl)s;
177        %(op_rd)s;
178        %(ea_code)s;
179        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
180
181        fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
182
183        return fault;
184    }
185}};
186
187def template MicroLoadCompleteAcc {{
188    Fault %(class_name)s::completeAcc(PacketPtr pkt,
189            %(CPU_exec_context)s * xc,
190            Trace::InstRecord * traceData) const
191    {
192        Fault fault = NoFault;
193
194        %(op_decl)s;
195        %(op_rd)s;
196
197        Mem = pkt->get<typeof(Mem)>();
198
199        %(code)s;
200
201        if(fault == NoFault)
202        {
203            %(op_wb)s;
204        }
205
206        return fault;
207    }
208}};
209
210// Store templates
211
212def template MicroStoreExecute {{
213    Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
214            Trace::InstRecord *traceData) const
215    {
216        Fault fault = NoFault;
217
218        Addr EA;
219        %(op_decl)s;
220        %(op_rd)s;
221        %(ea_code)s;
222        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
223
224        %(code)s;
225
226        if(fault == NoFault)
227        {
228            fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
229            if(fault == NoFault)
230            {
231                %(op_wb)s;
232            }
233        }
234
235        return fault;
236    }
237}};
238
239def template MicroStoreInitiateAcc {{
240    Fault %(class_name)s::initiateAcc(%(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 = write(xc, Mem, EA, (%(mem_flags)s) | segment);
256            if(fault == NoFault)
257            {
258                %(op_wb)s;
259            }
260        }
261        return fault;
262    }
263}};
264
265def template MicroStoreCompleteAcc {{
266    Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
267            Trace::InstRecord * traceData) const
268    {
269        return NoFault;
270    }
271}};
272
273// Common templates
274
275//This delcares the initiateAcc function in memory operations
276def template InitiateAccDeclare {{
277    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
278}};
279
280//This declares the completeAcc function in memory operations
281def template CompleteAccDeclare {{
282    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
283}};
284
285def template MicroLdStOpDeclare {{
286    class %(class_name)s : public %(base_class)s
287    {
288      protected:
289        void buildMe();
290
291      public:
292        %(class_name)s(ExtMachInst _machInst,
293                const char * instMnem,
294                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
295                uint8_t _scale, RegIndex _index, RegIndex _base,
296                uint64_t _disp, uint8_t _segment,
297                RegIndex _data,
298                uint8_t _dataSize, uint8_t _addressSize);
299
300        %(class_name)s(ExtMachInst _machInst,
301                const char * instMnem,
302                uint8_t _scale, RegIndex _index, RegIndex _base,
303                uint64_t _disp, uint8_t _segment,
304                RegIndex _data,
305                uint8_t _dataSize, uint8_t _addressSize);
306
307        %(BasicExecDeclare)s
308
309        %(InitiateAccDeclare)s
310
311        %(CompleteAccDeclare)s
312    };
313}};
314
315def template MicroLdStOpConstructor {{
316
317    inline void %(class_name)s::buildMe()
318    {
319        %(constructor)s;
320    }
321
322    inline %(class_name)s::%(class_name)s(
323            ExtMachInst machInst, const char * instMnem,
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        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
329                false, false, false, false,
330                _scale, _index, _base,
331                _disp, _segment, _data,
332                _dataSize, _addressSize, %(op_class)s)
333    {
334        buildMe();
335    }
336
337    inline %(class_name)s::%(class_name)s(
338            ExtMachInst machInst, const char * instMnem,
339            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
340            uint8_t _scale, RegIndex _index, RegIndex _base,
341            uint64_t _disp, uint8_t _segment,
342            RegIndex _data,
343            uint8_t _dataSize, uint8_t _addressSize) :
344        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
345                isMicro, isDelayed, isFirst, isLast,
346                _scale, _index, _base,
347                _disp, _segment, _data,
348                _dataSize, _addressSize, %(op_class)s)
349    {
350        buildMe();
351    }
352}};
353
354let {{
355    class LdStOp(X86Microop):
356        def __init__(self, data, segment, addr, disp, dataSize, addressSize):
357            self.data = data
358            [self.scale, self.index, self.base] = addr
359            self.disp = disp
360            self.segment = segment
361            self.dataSize = dataSize
362            self.addressSize = addressSize
363
364        def getAllocator(self, *microFlags):
365            allocator = '''new %(class_name)s(machInst, mnemonic
366                    %(flags)s, %(scale)s, %(index)s, %(base)s,
367                    %(disp)s, %(segment)s, %(data)s,
368                    %(dataSize)s, %(addressSize)s)''' % {
369                "class_name" : self.className,
370                "flags" : self.microFlagsText(microFlags),
371                "scale" : self.scale, "index" : self.index,
372                "base" : self.base,
373                "disp" : self.disp,
374                "segment" : self.segment, "data" : self.data,
375                "dataSize" : self.dataSize, "addressSize" : self.addressSize}
376            return allocator
377}};
378
379let {{
380
381    # Make these empty strings so that concatenating onto
382    # them will always work.
383    header_output = ""
384    decoder_output = ""
385    exec_output = ""
386
387    calculateEA = "EA = SegBase + scale * Index + Base + disp;"
388
389    def defineMicroLoadOp(mnemonic, code, mem_flags=0):
390        global header_output
391        global decoder_output
392        global exec_output
393        global microopClasses
394        Name = mnemonic
395        name = mnemonic.lower()
396
397        # Build up the all register version of this micro op
398        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
399                {"code": code,
400                 "ea_code": calculateEA,
401                 "mem_flags": mem_flags})
402        header_output += MicroLdStOpDeclare.subst(iop)
403        decoder_output += MicroLdStOpConstructor.subst(iop)
404        exec_output += MicroLoadExecute.subst(iop)
405        exec_output += MicroLoadInitiateAcc.subst(iop)
406        exec_output += MicroLoadCompleteAcc.subst(iop)
407
408        class LoadOp(LdStOp):
409            def __init__(self, data, segment, addr, disp = 0,
410                    dataSize="env.dataSize", addressSize="env.addressSize"):
411                super(LoadOp, self).__init__(data, segment,
412                        addr, disp, dataSize, addressSize)
413                self.className = Name
414                self.mnemonic = name
415
416        microopClasses[name] = LoadOp
417
418    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
419    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck')
420    defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
421
422    def defineMicroStoreOp(mnemonic, code, mem_flags=0):
423        global header_output
424        global decoder_output
425        global exec_output
426        global microopClasses
427        Name = mnemonic
428        name = mnemonic.lower()
429
430        # Build up the all register version of this micro op
431        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
432                {"code": code,
433                 "ea_code": calculateEA,
434                 "mem_flags": mem_flags})
435        header_output += MicroLdStOpDeclare.subst(iop)
436        decoder_output += MicroLdStOpConstructor.subst(iop)
437        exec_output += MicroStoreExecute.subst(iop)
438        exec_output += MicroStoreInitiateAcc.subst(iop)
439        exec_output += MicroStoreCompleteAcc.subst(iop)
440
441        class StoreOp(LdStOp):
442            def __init__(self, data, segment, addr, disp = 0,
443                    dataSize="env.dataSize", addressSize="env.addressSize"):
444                super(StoreOp, self).__init__(data, segment,
445                        addr, disp, dataSize, addressSize)
446                self.className = Name
447                self.mnemonic = name
448
449        microopClasses[name] = StoreOp
450
451    defineMicroStoreOp('St', 'Mem = Data;')
452    defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
453    defineMicroStoreOp('Stupd', '''
454            Mem = Data;
455            Base = merge(Base, EA - SegBase, addressSize);
456            ''');
457
458
459    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
460            {"code": "Data = merge(Data, EA, dataSize);",
461             "ea_code": calculateEA,
462             "mem_flags": 0})
463    header_output += MicroLeaDeclare.subst(iop)
464    decoder_output += MicroLdStOpConstructor.subst(iop)
465    exec_output += MicroLeaExecute.subst(iop)
466
467    class LeaOp(LdStOp):
468        def __init__(self, data, segment, addr, disp = 0,
469                dataSize="env.dataSize", addressSize="env.addressSize"):
470            super(LeaOp, self).__init__(data, segment,
471                    addr, disp, dataSize, addressSize)
472            self.className = "Lea"
473            self.mnemonic = "lea"
474
475    microopClasses["lea"] = LeaOp
476
477
478    iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
479            {"code": "xc->demapPage(EA, 0);",
480             "ea_code": calculateEA,
481             "mem_flags": 0})
482    header_output += MicroLeaDeclare.subst(iop)
483    decoder_output += MicroLdStOpConstructor.subst(iop)
484    exec_output += MicroLeaExecute.subst(iop)
485
486    class TiaOp(LdStOp):
487        def __init__(self, segment, addr, disp = 0,
488                dataSize="env.dataSize", addressSize="env.addressSize"):
489            super(TiaOp, self).__init__("NUM_INTREGS", segment,
490                    addr, disp, dataSize, addressSize)
491            self.className = "Tia"
492            self.mnemonic = "tia"
493
494    microopClasses["tia"] = TiaOp
495
496    iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp',
497            {"code": '''
498            Addr paddr;
499            fault = xc->translateDataWriteAddr(EA, paddr,
500                dataSize, (1 << segment));
501            ''',
502            "ea_code": calculateEA})
503    header_output += MicroLeaDeclare.subst(iop)
504    decoder_output += MicroLdStOpConstructor.subst(iop)
505    exec_output += MicroLeaExecute.subst(iop)
506
507    class CdaOp(LdStOp):
508        def __init__(self, segment, addr, disp = 0,
509                dataSize="env.dataSize", addressSize="env.addressSize"):
510            super(CdaOp, self).__init__("NUM_INTREGS", segment,
511                    addr, disp, dataSize, addressSize)
512            self.className = "Cda"
513            self.mnemonic = "cda"
514
515    microopClasses["cda"] = CdaOp
516}};
517
518