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