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