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