ldstop.isa revision 11329:82bb3ee706b3
1695SN/A// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
21762SN/A// Copyright (c) 2015 Advanced Micro Devices, Inc.
3695SN/A// All rights reserved.
4695SN/A//
5695SN/A// The license below extends only to copyright in the software and shall
6695SN/A// not be construed as granting a license to any other intellectual
7695SN/A// property including but not limited to intellectual property relating
8695SN/A// to a hardware implementation of the functionality of the software
9695SN/A// licensed hereunder.  You may use the software subject to the license
10695SN/A// terms below provided that you ensure that this notice is replicated
11695SN/A// unmodified and in its entirety in all distributions of the software,
12695SN/A// modified or unmodified, in source code or in binary form.
13695SN/A//
14695SN/A// Copyright (c) 2008 The Regents of The University of Michigan
15695SN/A// All rights reserved.
16695SN/A//
17695SN/A// Redistribution and use in source and binary forms, with or without
18695SN/A// modification, are permitted provided that the following conditions are
19695SN/A// met: redistributions of source code must retain the above copyright
20695SN/A// notice, this list of conditions and the following disclaimer;
21695SN/A// redistributions in binary form must reproduce the above copyright
22695SN/A// notice, this list of conditions and the following disclaimer in the
23695SN/A// documentation and/or other materials provided with the distribution;
24695SN/A// neither the name of the copyright holders nor the names of its
25695SN/A// contributors may be used to endorse or promote products derived from
26695SN/A// this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu//
282665Ssaidi@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29695SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30695SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31695SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32695SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33695SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34695SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35695SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36695SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37695SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38695SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39695SN/A//
40695SN/A// Authors: Gabe Black
41695SN/A
421717SN/A//////////////////////////////////////////////////////////////////////////
43695SN/A//
44695SN/A// LdStOp Microop templates
45695SN/A//
46695SN/A//////////////////////////////////////////////////////////////////////////
47729SN/A
48695SN/A// LEA template
49729SN/A
50695SN/Adef template MicroLeaExecute {{
51695SN/A    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
52695SN/A          Trace::InstRecord *traceData) const
53695SN/A    {
544078Sbinkertn@umich.edu        Fault fault = NoFault;
55695SN/A        Addr EA;
56695SN/A
57695SN/A        %(op_decl)s;
58695SN/A        %(op_rd)s;
59695SN/A        %(ea_code)s;
60695SN/A        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
61695SN/A
62695SN/A        %(code)s;
63695SN/A        if(fault == NoFault)
64695SN/A        {
65695SN/A            %(op_wb)s;
66695SN/A        }
67695SN/A
68695SN/A        return fault;
69695SN/A    }
70695SN/A}};
711020SN/A
721020SN/Adef template MicroLeaDeclare {{
731020SN/A    class %(class_name)s : public %(base_class)s
741020SN/A    {
751020SN/A      public:
761020SN/A        %(class_name)s(ExtMachInst _machInst,
77695SN/A                const char * instMnem, uint64_t setFlags,
78695SN/A                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
795883Snate@binkert.org                uint64_t _disp, InstRegIndex _segment,
805883Snate@binkert.org                InstRegIndex _data,
815883Snate@binkert.org                uint8_t _dataSize, uint8_t _addressSize,
825883Snate@binkert.org                Request::FlagsType _memFlags);
835883Snate@binkert.org
845883Snate@binkert.org        %(BasicExecDeclare)s
855883Snate@binkert.org    };
865883Snate@binkert.org}};
875883Snate@binkert.org
885883Snate@binkert.org// Load templates
895883Snate@binkert.org
905883Snate@binkert.orgdef template MicroLoadExecute {{
915883Snate@binkert.org    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
925883Snate@binkert.org          Trace::InstRecord *traceData) const
935883Snate@binkert.org    {
94695SN/A        Fault fault = NoFault;
95695SN/A        Addr EA;
96707SN/A
97695SN/A        %(op_decl)s;
98695SN/A        %(op_rd)s;
99695SN/A        %(ea_code)s;
100695SN/A        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
101695SN/A
102695SN/A        fault = readMemAtomic(xc, traceData, EA, Mem,
103695SN/A                              %(memDataSize)s, memFlags);
104695SN/A
105695SN/A        if (fault == NoFault) {
106695SN/A            %(code)s;
107695SN/A        } else if (memFlags & Request::PREFETCH) {
108707SN/A            // For prefetches, ignore any faults/exceptions.
1091609SN/A            return NoFault;
110707SN/A        }
111707SN/A        if(fault == NoFault)
112707SN/A        {
113707SN/A            %(op_wb)s;
114695SN/A        }
1151020SN/A
116695SN/A        return fault;
117695SN/A    }
118695SN/A}};
119695SN/A
120695SN/Adef template MicroLoadInitiateAcc {{
121695SN/A    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
122695SN/A            Trace::InstRecord * traceData) const
123695SN/A    {
124695SN/A        Fault fault = NoFault;
125695SN/A        Addr EA;
126695SN/A
127695SN/A        %(op_decl)s;
128707SN/A        %(op_rd)s;
129695SN/A        %(ea_code)s;
130695SN/A        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
131695SN/A
132695SN/A        fault = initiateMemRead(xc, traceData, EA,
133695SN/A                                %(memDataSize)s, memFlags);
134695SN/A
135707SN/A        return fault;
136695SN/A    }
137695SN/A}};
138695SN/A
139695SN/Adef template MicroLoadCompleteAcc {{
140695SN/A    Fault %(class_name)s::completeAcc(PacketPtr pkt,
141695SN/A            CPU_EXEC_CONTEXT * xc,
142695SN/A            Trace::InstRecord * traceData) const
143695SN/A    {
144695SN/A        Fault fault = NoFault;
145695SN/A
146695SN/A        %(op_decl)s;
147707SN/A        %(op_rd)s;
148695SN/A
149695SN/A        getMem(pkt, Mem, %(memDataSize)s, traceData);
150695SN/A
151695SN/A        %(code)s;
152695SN/A
153695SN/A        if(fault == NoFault)
1545883Snate@binkert.org        {
1555883Snate@binkert.org            %(op_wb)s;
1565883Snate@binkert.org        }
1575883Snate@binkert.org
1585883Snate@binkert.org        return fault;
1595883Snate@binkert.org    }
1604078Sbinkertn@umich.edu}};
161695SN/A
1624078Sbinkertn@umich.edu// Store templates
1634078Sbinkertn@umich.edu
1644078Sbinkertn@umich.edudef template MicroStoreExecute {{
165695SN/A    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT * xc,
166695SN/A            Trace::InstRecord *traceData) const
167695SN/A    {
1685606Snate@binkert.org        Fault fault = NoFault;
1695606Snate@binkert.org
1704078Sbinkertn@umich.edu        Addr EA;
1714078Sbinkertn@umich.edu        %(op_decl)s;
1724078Sbinkertn@umich.edu        %(op_rd)s;
1734078Sbinkertn@umich.edu        %(ea_code)s;
1744078Sbinkertn@umich.edu        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
1754078Sbinkertn@umich.edu
1764078Sbinkertn@umich.edu        %(code)s;
1774078Sbinkertn@umich.edu
1784078Sbinkertn@umich.edu        if(fault == NoFault)
1794078Sbinkertn@umich.edu        {
1804078Sbinkertn@umich.edu            fault = writeMemAtomic(xc, traceData, Mem, %(memDataSize)s, EA,
1814078Sbinkertn@umich.edu                    memFlags, NULL);
1824078Sbinkertn@umich.edu            if(fault == NoFault)
1835606Snate@binkert.org            {
1845606Snate@binkert.org                %(op_wb)s;
1855606Snate@binkert.org            }
1865606Snate@binkert.org        }
1874078Sbinkertn@umich.edu
188695SN/A        return fault;
189695SN/A    }
1904078Sbinkertn@umich.edu}};
1914078Sbinkertn@umich.edu
192695SN/Adef template MicroStoreInitiateAcc {{
1935606Snate@binkert.org    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
1945606Snate@binkert.org            Trace::InstRecord * traceData) const
195695SN/A    {
196695SN/A        Fault fault = NoFault;
197729SN/A
198        Addr EA;
199        %(op_decl)s;
200        %(op_rd)s;
201        %(ea_code)s;
202        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
203
204        %(code)s;
205
206        if(fault == NoFault)
207        {
208            fault = writeMemTiming(xc, traceData, Mem, %(memDataSize)s, EA,
209                    memFlags, NULL);
210        }
211        return fault;
212    }
213}};
214
215def template MicroStoreCompleteAcc {{
216    Fault %(class_name)s::completeAcc(PacketPtr pkt,
217            CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const
218    {
219        %(op_decl)s;
220        %(op_rd)s;
221        %(complete_code)s;
222        %(op_wb)s;
223        return NoFault;
224    }
225}};
226
227// Common templates
228
229//This delcares the initiateAcc function in memory operations
230def template InitiateAccDeclare {{
231    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
232}};
233
234//This declares the completeAcc function in memory operations
235def template CompleteAccDeclare {{
236    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
237}};
238
239def template MicroLdStOpDeclare {{
240    class %(class_name)s : public %(base_class)s
241    {
242      public:
243        %(class_name)s(ExtMachInst _machInst,
244                const char * instMnem, uint64_t setFlags,
245                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
246                uint64_t _disp, InstRegIndex _segment,
247                InstRegIndex _data,
248                uint8_t _dataSize, uint8_t _addressSize,
249                Request::FlagsType _memFlags);
250
251        %(BasicExecDeclare)s
252
253        %(InitiateAccDeclare)s
254
255        %(CompleteAccDeclare)s
256    };
257}};
258
259// LdStSplitOp is a load or store that uses a pair of regs as the
260// source or destination.  Used for cmpxchg{8,16}b.
261def template MicroLdStSplitOpDeclare {{
262    class %(class_name)s : public %(base_class)s
263    {
264      public:
265        %(class_name)s(ExtMachInst _machInst,
266                const char * instMnem, uint64_t setFlags,
267                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
268                uint64_t _disp, InstRegIndex _segment,
269                InstRegIndex _dataLow, InstRegIndex _dataHi,
270                uint8_t _dataSize, uint8_t _addressSize,
271                Request::FlagsType _memFlags);
272
273        %(BasicExecDeclare)s
274
275        %(InitiateAccDeclare)s
276
277        %(CompleteAccDeclare)s
278    };
279}};
280
281def template MicroLdStOpConstructor {{
282    %(class_name)s::%(class_name)s(
283            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
284            uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
285            uint64_t _disp, InstRegIndex _segment,
286            InstRegIndex _data,
287            uint8_t _dataSize, uint8_t _addressSize,
288            Request::FlagsType _memFlags) :
289        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
290                _scale, _index, _base,
291                _disp, _segment, _data,
292                _dataSize, _addressSize, _memFlags, %(op_class)s)
293    {
294        %(constructor)s;
295    }
296}};
297
298def template MicroLdStSplitOpConstructor {{
299    %(class_name)s::%(class_name)s(
300            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
301            uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
302            uint64_t _disp, InstRegIndex _segment,
303            InstRegIndex _dataLow, InstRegIndex _dataHi,
304            uint8_t _dataSize, uint8_t _addressSize,
305            Request::FlagsType _memFlags) :
306        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
307                _scale, _index, _base,
308                _disp, _segment, _dataLow, _dataHi,
309                _dataSize, _addressSize, _memFlags, %(op_class)s)
310    {
311        %(constructor)s;
312    }
313}};
314
315let {{
316    class LdStOp(X86Microop):
317        def __init__(self, data, segment, addr, disp,
318                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
319            self.data = data
320            [self.scale, self.index, self.base] = addr
321            self.disp = disp
322            self.segment = segment
323            self.dataSize = dataSize
324            self.addressSize = addressSize
325            self.memFlags = baseFlags
326            if atCPL0:
327                self.memFlags += " | (CPL0FlagBit << FlagShift)"
328            self.instFlags = ""
329            if prefetch:
330                self.memFlags += " | Request::PREFETCH"
331                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
332            if nonSpec:
333                self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
334            self.memFlags += " | (machInst.legacy.addr ? " + \
335                             "(AddrSizeFlagBit << FlagShift) : 0)"
336
337        def getAllocator(self, microFlags):
338            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
339                    %(flags)s, %(scale)s, %(index)s, %(base)s,
340                    %(disp)s, %(segment)s, %(data)s,
341                    %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
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    class BigLdStOp(X86Microop):
353        def __init__(self, data, segment, addr, disp,
354                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
355            self.data = data
356            [self.scale, self.index, self.base] = addr
357            self.disp = disp
358            self.segment = segment
359            self.dataSize = dataSize
360            self.addressSize = addressSize
361            self.memFlags = baseFlags
362            if atCPL0:
363                self.memFlags += " | (CPL0FlagBit << FlagShift)"
364            self.instFlags = ""
365            if prefetch:
366                self.memFlags += " | Request::PREFETCH"
367                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
368            if nonSpec:
369                self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
370            self.memFlags += " | (machInst.legacy.addr ? " + \
371                             "(AddrSizeFlagBit << FlagShift) : 0)"
372
373        def getAllocator(self, microFlags):
374            allocString = '''
375                (%(dataSize)s >= 4) ?
376                    (StaticInstPtr)(new %(class_name)sBig(machInst,
377                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
378                        %(base)s, %(disp)s, %(segment)s, %(data)s,
379                        %(dataSize)s, %(addressSize)s, %(memFlags)s)) :
380                    (StaticInstPtr)(new %(class_name)s(machInst,
381                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
382                        %(base)s, %(disp)s, %(segment)s, %(data)s,
383                        %(dataSize)s, %(addressSize)s, %(memFlags)s))
384            '''
385            allocator = allocString % {
386                "class_name" : self.className,
387                "flags" : self.microFlagsText(microFlags) + self.instFlags,
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    class LdStSplitOp(LdStOp):
397        def __init__(self, data, segment, addr, disp,
398                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
399            super(LdStSplitOp, self).__init__(0, segment, addr, disp,
400                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec)
401            (self.dataLow, self.dataHi) = data
402
403        def getAllocator(self, microFlags):
404            allocString = '''(StaticInstPtr)(new %(class_name)s(machInst,
405                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
406                        %(base)s, %(disp)s, %(segment)s,
407                        %(dataLow)s, %(dataHi)s,
408                        %(dataSize)s, %(addressSize)s, %(memFlags)s))
409            '''
410            allocator = allocString % {
411                "class_name" : self.className,
412                "flags" : self.microFlagsText(microFlags) + self.instFlags,
413                "scale" : self.scale, "index" : self.index,
414                "base" : self.base,
415                "disp" : self.disp,
416                "segment" : self.segment,
417                "dataLow" : self.dataLow, "dataHi" : self.dataHi,
418                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
419                "memFlags" : self.memFlags}
420            return allocator
421
422}};
423
424let {{
425
426    # Make these empty strings so that concatenating onto
427    # them will always work.
428    header_output = ""
429    decoder_output = ""
430    exec_output = ""
431
432    segmentEAExpr = \
433        'bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);'
434
435    calculateEA = 'EA = SegBase + ' + segmentEAExpr
436
437    def defineMicroLoadOp(mnemonic, code, bigCode='',
438                          mem_flags="0", big=True, nonSpec=False):
439        global header_output
440        global decoder_output
441        global exec_output
442        global microopClasses
443        Name = mnemonic
444        name = mnemonic.lower()
445
446        # Build up the all register version of this micro op
447        iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
448                              { "code": code,
449                                "ea_code": calculateEA,
450                                "memDataSize": "dataSize" })]
451        if big:
452            iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
453                                   { "code": bigCode,
454                                     "ea_code": calculateEA,
455                                     "memDataSize": "dataSize" })]
456        for iop in iops:
457            header_output += MicroLdStOpDeclare.subst(iop)
458            decoder_output += MicroLdStOpConstructor.subst(iop)
459            exec_output += MicroLoadExecute.subst(iop)
460            exec_output += MicroLoadInitiateAcc.subst(iop)
461            exec_output += MicroLoadCompleteAcc.subst(iop)
462
463        base = LdStOp
464        if big:
465            base = BigLdStOp
466        class LoadOp(base):
467            def __init__(self, data, segment, addr, disp = 0,
468                    dataSize="env.dataSize",
469                    addressSize="env.addressSize",
470                    atCPL0=False, prefetch=False, nonSpec=nonSpec):
471                super(LoadOp, self).__init__(data, segment, addr,
472                        disp, dataSize, addressSize, mem_flags,
473                        atCPL0, prefetch, nonSpec)
474                self.className = Name
475                self.mnemonic = name
476
477        microopClasses[name] = LoadOp
478
479    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);',
480                            'Data = Mem & mask(dataSize * 8);')
481    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
482                              'Data = Mem & mask(dataSize * 8);',
483                      '(StoreCheck << FlagShift)')
484    defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
485                               'Data = Mem & mask(dataSize * 8);',
486                      '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
487                      nonSpec=True)
488
489    defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False)
490
491    defineMicroLoadOp('Ldfp87', code='''
492        switch (dataSize)
493        {
494          case 4:
495            FpData_df = *(float *)&Mem;
496            break;
497          case 8:
498            FpData_df = *(double *)&Mem;
499            break;
500          default:
501            panic("Unhandled data size in LdFp87.\\n");
502        }
503    ''', big = False)
504
505    # Load integer from memory into x87 top-of-stack register.
506    # Used to implement fild instruction.
507    defineMicroLoadOp('Ldifp87', code='''
508        switch (dataSize)
509        {
510          case 2:
511            FpData_df = (int64_t)sext<16>(Mem);
512            break;
513          case 4:
514            FpData_df = (int64_t)sext<32>(Mem);
515            break;
516          case 8:
517            FpData_df = (int64_t)Mem;
518            break;
519          default:
520            panic("Unhandled data size in LdIFp87.\\n");
521        }
522    ''', big = False)
523
524    def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False):
525        global header_output
526        global decoder_output
527        global exec_output
528        global microopClasses
529        Name = mnemonic
530        name = mnemonic.lower()
531
532        iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
533                            { "code": code,
534                              "ea_code": calculateEA,
535                              "memDataSize": "2 * dataSize" })
536
537        header_output += MicroLdStSplitOpDeclare.subst(iop)
538        decoder_output += MicroLdStSplitOpConstructor.subst(iop)
539        exec_output += MicroLoadExecute.subst(iop)
540        exec_output += MicroLoadInitiateAcc.subst(iop)
541        exec_output += MicroLoadCompleteAcc.subst(iop)
542
543        class LoadOp(LdStSplitOp):
544            def __init__(self, data, segment, addr, disp = 0,
545                    dataSize="env.dataSize",
546                    addressSize="env.addressSize",
547                    atCPL0=False, prefetch=False, nonSpec=nonSpec):
548                super(LoadOp, self).__init__(data, segment, addr,
549                        disp, dataSize, addressSize, mem_flags,
550                        atCPL0, prefetch, nonSpec)
551                self.className = Name
552                self.mnemonic = name
553
554        microopClasses[name] = LoadOp
555
556    code = '''
557        switch (dataSize) {
558          case 4:
559            DataLow = bits(Mem_u2qw[0], 31, 0);
560            DataHi  = bits(Mem_u2qw[0], 63, 32);
561            break;
562          case 8:
563            DataLow = Mem_u2qw[0];
564            DataHi  = Mem_u2qw[1];
565            break;
566          default:
567            panic("Unhandled data size %d in LdSplit.\\n", dataSize);
568        }'''
569
570    defineMicroLoadSplitOp('LdSplit', code,
571                           '(StoreCheck << FlagShift)')
572
573    defineMicroLoadSplitOp('LdSplitl', code,
574                           '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
575                           nonSpec=True)
576
577    def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"):
578        global header_output
579        global decoder_output
580        global exec_output
581        global microopClasses
582        Name = mnemonic
583        name = mnemonic.lower()
584
585        # Build up the all register version of this micro op
586        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
587                            { "code": code,
588                              "complete_code": completeCode,
589                              "ea_code": calculateEA,
590                              "memDataSize": "dataSize" })
591        header_output += MicroLdStOpDeclare.subst(iop)
592        decoder_output += MicroLdStOpConstructor.subst(iop)
593        exec_output += MicroStoreExecute.subst(iop)
594        exec_output += MicroStoreInitiateAcc.subst(iop)
595        exec_output += MicroStoreCompleteAcc.subst(iop)
596
597        class StoreOp(LdStOp):
598            def __init__(self, data, segment, addr, disp = 0,
599                    dataSize="env.dataSize",
600                    addressSize="env.addressSize",
601                    atCPL0=False, nonSpec=False):
602                super(StoreOp, self).__init__(data, segment, addr, disp,
603                        dataSize, addressSize, mem_flags, atCPL0, False,
604                        nonSpec)
605                self.className = Name
606                self.mnemonic = name
607
608        microopClasses[name] = StoreOp
609
610    defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
611    defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
612            mem_flags="Request::LOCKED_RMW")
613
614    defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;')
615
616    defineMicroStoreOp('Stfp87', code='''
617        switch (dataSize)
618        {
619          case 4: {
620            float single(FpData_df);
621            Mem = *(uint32_t *)&single;
622          } break;
623          case 8:
624            Mem = *(uint64_t *)&FpData_df;
625            break;
626          default:
627            panic("Unhandled data size in StFp87.\\n");
628        }
629    ''')
630
631    defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
632
633    def defineMicroStoreSplitOp(mnemonic, code,
634                                completeCode="", mem_flags="0"):
635        global header_output
636        global decoder_output
637        global exec_output
638        global microopClasses
639        Name = mnemonic
640        name = mnemonic.lower()
641
642        iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
643                            { "code": code,
644                              "complete_code": completeCode,
645                              "ea_code": calculateEA,
646                              "memDataSize": "2 * dataSize" })
647
648        header_output += MicroLdStSplitOpDeclare.subst(iop)
649        decoder_output += MicroLdStSplitOpConstructor.subst(iop)
650        exec_output += MicroStoreExecute.subst(iop)
651        exec_output += MicroStoreInitiateAcc.subst(iop)
652        exec_output += MicroStoreCompleteAcc.subst(iop)
653
654        class StoreOp(LdStSplitOp):
655            def __init__(self, data, segment, addr, disp = 0,
656                    dataSize="env.dataSize",
657                    addressSize="env.addressSize",
658                    atCPL0=False, nonSpec=False):
659                super(StoreOp, self).__init__(data, segment, addr, disp,
660                        dataSize, addressSize, mem_flags, atCPL0, False,
661                        nonSpec)
662                self.className = Name
663                self.mnemonic = name
664
665        microopClasses[name] = StoreOp
666
667    code = '''
668        switch (dataSize) {
669          case 4:
670            Mem_u2qw[0] = (DataHi << 32) | DataLow;
671            break;
672          case 8:
673            Mem_u2qw[0] = DataLow;
674            Mem_u2qw[1] = DataHi;
675            break;
676          default:
677            panic("Unhandled data size %d in StSplit.\\n", dataSize);
678        }'''
679
680    defineMicroStoreSplitOp('StSplit', code);
681
682    defineMicroStoreSplitOp('StSplitul', code,
683                            mem_flags='Request::LOCKED_RMW')
684
685    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
686                        { "code": "Data = merge(Data, EA, dataSize);",
687                          "ea_code": "EA = " + segmentEAExpr,
688                          "memDataSize": "dataSize" })
689    header_output += MicroLeaDeclare.subst(iop)
690    decoder_output += MicroLdStOpConstructor.subst(iop)
691    exec_output += MicroLeaExecute.subst(iop)
692
693    class LeaOp(LdStOp):
694        def __init__(self, data, segment, addr, disp = 0,
695                dataSize="env.dataSize", addressSize="env.addressSize"):
696            super(LeaOp, self).__init__(data, segment, addr, disp,
697                    dataSize, addressSize, "0", False, False, False)
698            self.className = "Lea"
699            self.mnemonic = "lea"
700
701    microopClasses["lea"] = LeaOp
702
703
704    iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
705                        { "code": "xc->demapPage(EA, 0);",
706                          "ea_code": calculateEA,
707                          "memDataSize": "dataSize" })
708    header_output += MicroLeaDeclare.subst(iop)
709    decoder_output += MicroLdStOpConstructor.subst(iop)
710    exec_output += MicroLeaExecute.subst(iop)
711
712    class TiaOp(LdStOp):
713        def __init__(self, segment, addr, disp = 0,
714                dataSize="env.dataSize",
715                addressSize="env.addressSize"):
716            super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
717                    addr, disp, dataSize, addressSize, "0", False, False,
718                    False)
719            self.className = "Tia"
720            self.mnemonic = "tia"
721
722    microopClasses["tia"] = TiaOp
723
724    class CdaOp(LdStOp):
725        def __init__(self, segment, addr, disp = 0,
726                dataSize="env.dataSize",
727                addressSize="env.addressSize", atCPL0=False):
728            super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
729                    addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
730                    atCPL0, False, False)
731            self.className = "Cda"
732            self.mnemonic = "cda"
733
734    microopClasses["cda"] = CdaOp
735}};
736
737