ldstop.isa revision 11303:f694764d656d
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 *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 *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 = readMemAtomic(xc, traceData, EA, Mem, dataSize, 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 * 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 = initiateMemRead(xc, traceData, EA, dataSize, memFlags);
131
132        return fault;
133    }
134}};
135
136def template MicroLoadCompleteAcc {{
137    Fault %(class_name)s::completeAcc(PacketPtr pkt,
138            CPU_EXEC_CONTEXT * xc,
139            Trace::InstRecord * traceData) const
140    {
141        Fault fault = NoFault;
142
143        %(op_decl)s;
144        %(op_rd)s;
145
146        Mem = getMem(pkt, dataSize, traceData);
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 * 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 = writeMemAtomic(xc, traceData, Mem, dataSize, EA,
178                    memFlags, NULL);
179            if(fault == NoFault)
180            {
181                %(op_wb)s;
182            }
183        }
184
185        return fault;
186    }
187}};
188
189def template MicroStoreInitiateAcc {{
190    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
191            Trace::InstRecord * traceData) const
192    {
193        Fault fault = NoFault;
194
195        Addr EA;
196        %(op_decl)s;
197        %(op_rd)s;
198        %(ea_code)s;
199        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
200
201        %(code)s;
202
203        if(fault == NoFault)
204        {
205            fault = writeMemTiming(xc, traceData, Mem, dataSize, EA,
206                    memFlags, NULL);
207        }
208        return fault;
209    }
210}};
211
212def template MicroStoreCompleteAcc {{
213    Fault %(class_name)s::completeAcc(PacketPtr pkt,
214            CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const
215    {
216        %(op_decl)s;
217        %(op_rd)s;
218        %(complete_code)s;
219        %(op_wb)s;
220        return NoFault;
221    }
222}};
223
224// Common templates
225
226//This delcares the initiateAcc function in memory operations
227def template InitiateAccDeclare {{
228    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
229}};
230
231//This declares the completeAcc function in memory operations
232def template CompleteAccDeclare {{
233    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
234}};
235
236def template MicroLdStOpDeclare {{
237    class %(class_name)s : public %(base_class)s
238    {
239      public:
240        %(class_name)s(ExtMachInst _machInst,
241                const char * instMnem, uint64_t setFlags,
242                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
243                uint64_t _disp, InstRegIndex _segment,
244                InstRegIndex _data,
245                uint8_t _dataSize, uint8_t _addressSize,
246                Request::FlagsType _memFlags);
247
248        %(BasicExecDeclare)s
249
250        %(InitiateAccDeclare)s
251
252        %(CompleteAccDeclare)s
253    };
254}};
255
256def template MicroLdStOpConstructor {{
257    %(class_name)s::%(class_name)s(
258            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
259            uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
260            uint64_t _disp, InstRegIndex _segment,
261            InstRegIndex _data,
262            uint8_t _dataSize, uint8_t _addressSize,
263            Request::FlagsType _memFlags) :
264        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
265                _scale, _index, _base,
266                _disp, _segment, _data,
267                _dataSize, _addressSize, _memFlags, %(op_class)s)
268    {
269        %(constructor)s;
270    }
271}};
272
273let {{
274    class LdStOp(X86Microop):
275        def __init__(self, data, segment, addr, disp,
276                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
277            self.data = data
278            [self.scale, self.index, self.base] = addr
279            self.disp = disp
280            self.segment = segment
281            self.dataSize = dataSize
282            self.addressSize = addressSize
283            self.memFlags = baseFlags
284            if atCPL0:
285                self.memFlags += " | (CPL0FlagBit << FlagShift)"
286            self.instFlags = ""
287            if prefetch:
288                self.memFlags += " | Request::PREFETCH"
289                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
290            if nonSpec:
291                self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
292            self.memFlags += " | (machInst.legacy.addr ? " + \
293                             "(AddrSizeFlagBit << FlagShift) : 0)"
294
295        def getAllocator(self, microFlags):
296            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
297                    %(flags)s, %(scale)s, %(index)s, %(base)s,
298                    %(disp)s, %(segment)s, %(data)s,
299                    %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
300                "class_name" : self.className,
301                "flags" : self.microFlagsText(microFlags) + self.instFlags,
302                "scale" : self.scale, "index" : self.index,
303                "base" : self.base,
304                "disp" : self.disp,
305                "segment" : self.segment, "data" : self.data,
306                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
307                "memFlags" : self.memFlags}
308            return allocator
309
310    class BigLdStOp(X86Microop):
311        def __init__(self, data, segment, addr, disp,
312                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
313            self.data = data
314            [self.scale, self.index, self.base] = addr
315            self.disp = disp
316            self.segment = segment
317            self.dataSize = dataSize
318            self.addressSize = addressSize
319            self.memFlags = baseFlags
320            if atCPL0:
321                self.memFlags += " | (CPL0FlagBit << FlagShift)"
322            self.instFlags = ""
323            if prefetch:
324                self.memFlags += " | Request::PREFETCH"
325                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
326            if nonSpec:
327                self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
328            self.memFlags += " | (machInst.legacy.addr ? " + \
329                             "(AddrSizeFlagBit << FlagShift) : 0)"
330
331        def getAllocator(self, microFlags):
332            allocString = '''
333                (%(dataSize)s >= 4) ?
334                    (StaticInstPtr)(new %(class_name)sBig(machInst,
335                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
336                        %(base)s, %(disp)s, %(segment)s, %(data)s,
337                        %(dataSize)s, %(addressSize)s, %(memFlags)s)) :
338                    (StaticInstPtr)(new %(class_name)s(machInst,
339                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
340                        %(base)s, %(disp)s, %(segment)s, %(data)s,
341                        %(dataSize)s, %(addressSize)s, %(memFlags)s))
342            '''
343            allocator = allocString % {
344                "class_name" : self.className,
345                "flags" : self.microFlagsText(microFlags) + self.instFlags,
346                "scale" : self.scale, "index" : self.index,
347                "base" : self.base,
348                "disp" : self.disp,
349                "segment" : self.segment, "data" : self.data,
350                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
351                "memFlags" : self.memFlags}
352            return allocator
353}};
354
355let {{
356
357    # Make these empty strings so that concatenating onto
358    # them will always work.
359    header_output = ""
360    decoder_output = ""
361    exec_output = ""
362
363    calculateEA = '''
364    EA = SegBase + bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
365    '''
366
367    def defineMicroLoadOp(mnemonic, code, bigCode='',
368                          mem_flags="0", big=True):
369        global header_output
370        global decoder_output
371        global exec_output
372        global microopClasses
373        Name = mnemonic
374        name = mnemonic.lower()
375
376        # Build up the all register version of this micro op
377        iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
378                {"code": code, "ea_code": calculateEA})]
379        if big:
380            iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
381                     {"code": bigCode, "ea_code": calculateEA})]
382        for iop in iops:
383            header_output += MicroLdStOpDeclare.subst(iop)
384            decoder_output += MicroLdStOpConstructor.subst(iop)
385            exec_output += MicroLoadExecute.subst(iop)
386            exec_output += MicroLoadInitiateAcc.subst(iop)
387            exec_output += MicroLoadCompleteAcc.subst(iop)
388
389        base = LdStOp
390        if big:
391            base = BigLdStOp
392        class LoadOp(base):
393            def __init__(self, data, segment, addr, disp = 0,
394                    dataSize="env.dataSize",
395                    addressSize="env.addressSize",
396                    atCPL0=False, prefetch=False, nonSpec=False):
397                super(LoadOp, self).__init__(data, segment, addr,
398                        disp, dataSize, addressSize, mem_flags,
399                        atCPL0, prefetch, nonSpec)
400                self.className = Name
401                self.mnemonic = name
402
403        microopClasses[name] = LoadOp
404
405    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);',
406                            'Data = Mem & mask(dataSize * 8);')
407    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
408                              'Data = Mem & mask(dataSize * 8);',
409                      '(StoreCheck << FlagShift)')
410    defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
411                               'Data = Mem & mask(dataSize * 8);',
412                      '(StoreCheck << FlagShift) | Request::LOCKED_RMW')
413
414    defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False)
415
416    defineMicroLoadOp('Ldfp87', code='''
417        switch (dataSize)
418        {
419          case 4:
420            FpData_df = *(float *)&Mem;
421            break;
422          case 8:
423            FpData_df = *(double *)&Mem;
424            break;
425          default:
426            panic("Unhandled data size in LdFp87.\\n");
427        }
428    ''', big = False)
429
430    # Load integer from memory into x87 top-of-stack register.
431    # Used to implement fild instruction.
432    defineMicroLoadOp('Ldifp87', code='''
433        switch (dataSize)
434        {
435          case 2:
436            FpData_df = (int64_t)sext<16>(Mem);
437            break;
438          case 4:
439            FpData_df = (int64_t)sext<32>(Mem);
440            break;
441          case 8:
442            FpData_df = (int64_t)Mem;
443            break;
444          default:
445            panic("Unhandled data size in LdIFp87.\\n");
446        }
447    ''', big = False)
448
449    def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"):
450        global header_output
451        global decoder_output
452        global exec_output
453        global microopClasses
454        Name = mnemonic
455        name = mnemonic.lower()
456
457        # Build up the all register version of this micro op
458        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
459                {"code": code,
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, nonSpec=False):
473                super(StoreOp, self).__init__(data, segment, addr, disp,
474                        dataSize, addressSize, mem_flags, atCPL0, False,
475                        nonSpec)
476                self.className = Name
477                self.mnemonic = name
478
479        microopClasses[name] = StoreOp
480
481    defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
482    defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
483            mem_flags="Request::LOCKED_RMW")
484
485    defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;')
486
487    defineMicroStoreOp('Stfp87', code='''
488        switch (dataSize)
489        {
490          case 4: {
491            float single(FpData_df);
492            Mem = *(uint32_t *)&single;
493          } break;
494          case 8:
495            Mem = *(uint64_t *)&FpData_df;
496            break;
497          default:
498            panic("Unhandled data size in StFp87.\\n");
499        }
500    ''')
501
502    defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
503
504    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
505            {"code": "Data = merge(Data, EA, dataSize);",
506             "ea_code": '''
507             EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
508             '''})
509    header_output += MicroLeaDeclare.subst(iop)
510    decoder_output += MicroLdStOpConstructor.subst(iop)
511    exec_output += MicroLeaExecute.subst(iop)
512
513    class LeaOp(LdStOp):
514        def __init__(self, data, segment, addr, disp = 0,
515                dataSize="env.dataSize", addressSize="env.addressSize"):
516            super(LeaOp, self).__init__(data, segment, addr, disp,
517                    dataSize, addressSize, "0", False, False, False)
518            self.className = "Lea"
519            self.mnemonic = "lea"
520
521    microopClasses["lea"] = LeaOp
522
523
524    iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
525            {"code": "xc->demapPage(EA, 0);",
526             "ea_code": calculateEA})
527    header_output += MicroLeaDeclare.subst(iop)
528    decoder_output += MicroLdStOpConstructor.subst(iop)
529    exec_output += MicroLeaExecute.subst(iop)
530
531    class TiaOp(LdStOp):
532        def __init__(self, segment, addr, disp = 0,
533                dataSize="env.dataSize",
534                addressSize="env.addressSize"):
535            super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
536                    addr, disp, dataSize, addressSize, "0", False, False,
537                    False)
538            self.className = "Tia"
539            self.mnemonic = "tia"
540
541    microopClasses["tia"] = TiaOp
542
543    class CdaOp(LdStOp):
544        def __init__(self, segment, addr, disp = 0,
545                dataSize="env.dataSize",
546                addressSize="env.addressSize", atCPL0=False):
547            super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
548                    addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
549                    atCPL0, False, False)
550            self.className = "Cda"
551            self.mnemonic = "cda"
552
553    microopClasses["cda"] = CdaOp
554}};
555
556