ldstop.isa revision 6079:f39c5598a302
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                Request::FlagsType _memFlags);
129
130        %(class_name)s(ExtMachInst _machInst,
131                const char * instMnem,
132                uint8_t _scale, RegIndex _index, RegIndex _base,
133                uint64_t _disp, uint8_t _segment,
134                RegIndex _data,
135                uint8_t _dataSize, uint8_t _addressSize,
136                Request::FlagsType _memFlags);
137
138        %(BasicExecDeclare)s
139    };
140}};
141
142// Load templates
143
144def template MicroLoadExecute {{
145    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
146          Trace::InstRecord *traceData) const
147    {
148        Fault fault = NoFault;
149        Addr EA;
150
151        %(op_decl)s;
152        %(op_rd)s;
153        %(ea_code)s;
154        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
155
156        fault = read(xc, EA, Mem, memFlags);
157
158        if (fault == NoFault) {
159            %(code)s;
160        } else if (memFlags & Request::PF_EXCLUSIVE) {
161            // For prefetches, ignore any faults/exceptions.
162            return NoFault;
163        }
164        if(fault == NoFault)
165        {
166            %(op_wb)s;
167        }
168
169        return fault;
170    }
171}};
172
173def template MicroLoadInitiateAcc {{
174    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
175            Trace::InstRecord * traceData) const
176    {
177        Fault fault = NoFault;
178        Addr EA;
179
180        %(op_decl)s;
181        %(op_rd)s;
182        %(ea_code)s;
183        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
184
185        fault = read(xc, EA, Mem, memFlags);
186
187        return fault;
188    }
189}};
190
191def template MicroLoadCompleteAcc {{
192    Fault %(class_name)s::completeAcc(PacketPtr pkt,
193            %(CPU_exec_context)s * xc,
194            Trace::InstRecord * traceData) const
195    {
196        Fault fault = NoFault;
197
198        %(op_decl)s;
199        %(op_rd)s;
200
201        Mem = get(pkt);
202
203        %(code)s;
204
205        if(fault == NoFault)
206        {
207            %(op_wb)s;
208        }
209
210        return fault;
211    }
212}};
213
214// Store templates
215
216def template MicroStoreExecute {{
217    Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
218            Trace::InstRecord *traceData) const
219    {
220        Fault fault = NoFault;
221
222        Addr EA;
223        %(op_decl)s;
224        %(op_rd)s;
225        %(ea_code)s;
226        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
227
228        %(code)s;
229
230        if(fault == NoFault)
231        {
232            fault = write(xc, Mem, EA, memFlags);
233            if(fault == NoFault)
234            {
235                %(post_code)s;
236                %(op_wb)s;
237            }
238        }
239
240        return fault;
241    }
242}};
243
244def template MicroStoreInitiateAcc {{
245    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
246            Trace::InstRecord * traceData) const
247    {
248        Fault fault = NoFault;
249
250        Addr EA;
251        %(op_decl)s;
252        %(op_rd)s;
253        %(ea_code)s;
254        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
255
256        %(code)s;
257
258        if(fault == NoFault)
259        {
260            write(xc, Mem, EA, memFlags);
261        }
262        return fault;
263    }
264}};
265
266def template MicroStoreCompleteAcc {{
267    Fault %(class_name)s::completeAcc(PacketPtr pkt,
268            %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
269    {
270        %(op_decl)s;
271        %(op_rd)s;
272        %(complete_code)s;
273        %(op_wb)s;
274        return NoFault;
275    }
276}};
277
278// Common templates
279
280//This delcares the initiateAcc function in memory operations
281def template InitiateAccDeclare {{
282    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
283}};
284
285//This declares the completeAcc function in memory operations
286def template CompleteAccDeclare {{
287    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
288}};
289
290def template MicroLdStOpDeclare {{
291    class %(class_name)s : public %(base_class)s
292    {
293      protected:
294        void buildMe();
295
296      public:
297        %(class_name)s(ExtMachInst _machInst,
298                const char * instMnem,
299                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
300                uint8_t _scale, RegIndex _index, RegIndex _base,
301                uint64_t _disp, uint8_t _segment,
302                RegIndex _data,
303                uint8_t _dataSize, uint8_t _addressSize,
304                Request::FlagsType _memFlags);
305
306        %(class_name)s(ExtMachInst _machInst,
307                const char * instMnem,
308                uint8_t _scale, RegIndex _index, RegIndex _base,
309                uint64_t _disp, uint8_t _segment,
310                RegIndex _data,
311                uint8_t _dataSize, uint8_t _addressSize,
312                Request::FlagsType _memFlags);
313
314        %(BasicExecDeclare)s
315
316        %(InitiateAccDeclare)s
317
318        %(CompleteAccDeclare)s
319    };
320}};
321
322def template MicroLdStOpConstructor {{
323
324    inline void %(class_name)s::buildMe()
325    {
326        %(constructor)s;
327    }
328
329    inline %(class_name)s::%(class_name)s(
330            ExtMachInst machInst, 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            Request::FlagsType _memFlags) :
336        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
337                false, false, false, false,
338                _scale, _index, _base,
339                _disp, _segment, _data,
340                _dataSize, _addressSize, _memFlags, %(op_class)s)
341    {
342        buildMe();
343    }
344
345    inline %(class_name)s::%(class_name)s(
346            ExtMachInst machInst, const char * instMnem,
347            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
348            uint8_t _scale, RegIndex _index, RegIndex _base,
349            uint64_t _disp, uint8_t _segment,
350            RegIndex _data,
351            uint8_t _dataSize, uint8_t _addressSize,
352            Request::FlagsType _memFlags) :
353        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
354                isMicro, isDelayed, isFirst, isLast,
355                _scale, _index, _base,
356                _disp, _segment, _data,
357                _dataSize, _addressSize, _memFlags, %(op_class)s)
358    {
359        buildMe();
360    }
361}};
362
363let {{
364    class LdStOp(X86Microop):
365        def __init__(self, data, segment, addr, disp,
366                dataSize, addressSize, baseFlags, atCPL0, prefetch):
367            self.data = data
368            [self.scale, self.index, self.base] = addr
369            self.disp = disp
370            self.segment = segment
371            self.dataSize = dataSize
372            self.addressSize = addressSize
373            self.memFlags = baseFlags
374            if atCPL0:
375                self.memFlags += " | (CPL0FlagBit << FlagShift)"
376            if prefetch:
377                self.memFlags += " | Request::PF_EXCLUSIVE"
378            self.memFlags += " | (machInst.legacy.addr ? " + \
379                             "(AddrSizeFlagBit << FlagShift) : 0)"
380
381        def getAllocator(self, *microFlags):
382            allocator = '''new %(class_name)s(machInst, macrocodeBlock
383                    %(flags)s, %(scale)s, %(index)s, %(base)s,
384                    %(disp)s, %(segment)s, %(data)s,
385                    %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
386                "class_name" : self.className,
387                "flags" : self.microFlagsText(microFlags),
388                "scale" : self.scale, "index" : self.index,
389                "base" : self.base,
390                "disp" : self.disp,
391                "segment" : self.segment, "data" : self.data,
392                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
393                "memFlags" : self.memFlags}
394            return allocator
395}};
396
397let {{
398
399    # Make these empty strings so that concatenating onto
400    # them will always work.
401    header_output = ""
402    decoder_output = ""
403    exec_output = ""
404
405    calculateEA = '''
406    EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0);
407    '''
408
409    def defineMicroLoadOp(mnemonic, code, mem_flags="0"):
410        global header_output
411        global decoder_output
412        global exec_output
413        global microopClasses
414        Name = mnemonic
415        name = mnemonic.lower()
416
417        # Build up the all register version of this micro op
418        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
419                {"code": code,
420                 "ea_code": calculateEA})
421        header_output += MicroLdStOpDeclare.subst(iop)
422        decoder_output += MicroLdStOpConstructor.subst(iop)
423        exec_output += MicroLoadExecute.subst(iop)
424        exec_output += MicroLoadInitiateAcc.subst(iop)
425        exec_output += MicroLoadCompleteAcc.subst(iop)
426
427        class LoadOp(LdStOp):
428            def __init__(self, data, segment, addr, disp = 0,
429                    dataSize="env.dataSize",
430                    addressSize="env.addressSize",
431                    atCPL0=False, prefetch=False):
432                super(LoadOp, self).__init__(data, segment, addr,
433                        disp, dataSize, addressSize, mem_flags,
434                        atCPL0, prefetch)
435                self.className = Name
436                self.mnemonic = name
437
438        microopClasses[name] = LoadOp
439
440    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
441    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
442            'X86ISA::StoreCheck')
443    defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
444            'X86ISA::StoreCheck | Request::LOCKED')
445    defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
446
447    def defineMicroStoreOp(mnemonic, code, \
448            postCode="", completeCode="", mem_flags="0"):
449        global header_output
450        global decoder_output
451        global exec_output
452        global microopClasses
453        Name = mnemonic
454        name = mnemonic.lower()
455
456        # Build up the all register version of this micro op
457        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
458                {"code": code,
459                 "post_code": postCode,
460                 "complete_code": completeCode,
461                 "ea_code": calculateEA})
462        header_output += MicroLdStOpDeclare.subst(iop)
463        decoder_output += MicroLdStOpConstructor.subst(iop)
464        exec_output += MicroStoreExecute.subst(iop)
465        exec_output += MicroStoreInitiateAcc.subst(iop)
466        exec_output += MicroStoreCompleteAcc.subst(iop)
467
468        class StoreOp(LdStOp):
469            def __init__(self, data, segment, addr, disp = 0,
470                    dataSize="env.dataSize",
471                    addressSize="env.addressSize",
472                    atCPL0=False):
473                super(StoreOp, self).__init__(data, segment, addr,
474                        disp, dataSize, addressSize, mem_flags, atCPL0, False)
475                self.className = Name
476                self.mnemonic = name
477
478        microopClasses[name] = StoreOp
479
480    defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
481    defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
482    defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);',
483            'Base = merge(Base, EA - SegBase, addressSize);',
484            'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);');
485    defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
486
487    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
488            {"code": "Data = merge(Data, EA, dataSize);",
489             "ea_code": '''
490             EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
491             '''})
492    header_output += MicroLeaDeclare.subst(iop)
493    decoder_output += MicroLdStOpConstructor.subst(iop)
494    exec_output += MicroLeaExecute.subst(iop)
495
496    class LeaOp(LdStOp):
497        def __init__(self, data, segment, addr, disp = 0,
498                dataSize="env.dataSize", addressSize="env.addressSize"):
499            super(LeaOp, self).__init__(data, segment,
500                    addr, disp, dataSize, addressSize, "0", False, False)
501            self.className = "Lea"
502            self.mnemonic = "lea"
503
504    microopClasses["lea"] = LeaOp
505
506
507    iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
508            {"code": "xc->demapPage(EA, 0);",
509             "ea_code": calculateEA})
510    header_output += MicroLeaDeclare.subst(iop)
511    decoder_output += MicroLdStOpConstructor.subst(iop)
512    exec_output += MicroLeaExecute.subst(iop)
513
514    class TiaOp(LdStOp):
515        def __init__(self, segment, addr, disp = 0,
516                dataSize="env.dataSize",
517                addressSize="env.addressSize"):
518            super(TiaOp, self).__init__("NUM_INTREGS", segment,
519                    addr, disp, dataSize, addressSize, "0", False, False)
520            self.className = "Tia"
521            self.mnemonic = "tia"
522
523    microopClasses["tia"] = TiaOp
524
525    class CdaOp(LdStOp):
526        def __init__(self, segment, addr, disp = 0,
527                dataSize="env.dataSize",
528                addressSize="env.addressSize", atCPL0=False):
529            super(CdaOp, self).__init__("NUM_INTREGS", segment,
530                    addr, disp, dataSize, addressSize, "0", atCPL0, False)
531            self.className = "Cda"
532            self.mnemonic = "cda"
533
534    microopClasses["cda"] = CdaOp
535}};
536
537