ldstop.isa revision 11829
12SN/A// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
214027Stiago.muck@arm.com// Copyright (c) 2015 Advanced Micro Devices, Inc.
310688Sandreas.hansson@arm.com// All rights reserved.
410688Sandreas.hansson@arm.com//
510688Sandreas.hansson@arm.com// The license below extends only to copyright in the software and shall
610688Sandreas.hansson@arm.com// not be construed as granting a license to any other intellectual
710688Sandreas.hansson@arm.com// property including but not limited to intellectual property relating
810688Sandreas.hansson@arm.com// to a hardware implementation of the functionality of the software
910688Sandreas.hansson@arm.com// licensed hereunder.  You may use the software subject to the license
1010688Sandreas.hansson@arm.com// terms below provided that you ensure that this notice is replicated
1110688Sandreas.hansson@arm.com// unmodified and in its entirety in all distributions of the software,
1210688Sandreas.hansson@arm.com// modified or unmodified, in source code or in binary form.
1310688Sandreas.hansson@arm.com//
141762SN/A// Copyright (c) 2008 The Regents of The University of Michigan
152SN/A// All rights reserved.
162SN/A//
172SN/A// Redistribution and use in source and binary forms, with or without
182SN/A// modification, are permitted provided that the following conditions are
192SN/A// met: redistributions of source code must retain the above copyright
202SN/A// notice, this list of conditions and the following disclaimer;
212SN/A// redistributions in binary form must reproduce the above copyright
222SN/A// notice, this list of conditions and the following disclaimer in the
232SN/A// documentation and/or other materials provided with the distribution;
242SN/A// neither the name of the copyright holders nor the names of its
252SN/A// contributors may be used to endorse or promote products derived from
262SN/A// this software without specific prior written permission.
272SN/A//
282SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392665SN/A//
402665SN/A// Authors: Gabe Black
412665SN/A
4210688Sandreas.hansson@arm.com//////////////////////////////////////////////////////////////////////////
432SN/A//
442SN/A// LdStOp Microop templates
4511793Sbrandon.potter@amd.com//
4611793Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////////////
4710348Sandreas.hansson@arm.com
48146SN/A// LEA template
4911800Sbrandon.potter@amd.com
508232Snate@binkert.orgdef template MicroLeaExecute {{
5110688Sandreas.hansson@arm.com    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
52695SN/A          Trace::InstRecord *traceData) const
538832SAli.Saidi@ARM.com    {
542SN/A        Fault fault = NoFault;
552SN/A        Addr EA;
562SN/A
5710688Sandreas.hansson@arm.com        %(op_decl)s;
581298SN/A        %(op_rd)s;
593187SN/A        %(ea_code)s;
608975Sandreas.hansson@arm.com        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
613187SN/A
6210688Sandreas.hansson@arm.com        %(code)s;
633187SN/A        if(fault == NoFault)
643187SN/A        {
653187SN/A            %(op_wb)s;
663187SN/A        }
6710713Sandreas.hansson@arm.com
683187SN/A        return fault;
6910688Sandreas.hansson@arm.com    }
703187SN/A}};
713187SN/A
7210688Sandreas.hansson@arm.comdef template MicroLeaDeclare {{
733349SN/A    class %(class_name)s : public %(base_class)s
743262SN/A    {
7510688Sandreas.hansson@arm.com      public:
763262SN/A        %(class_name)s(ExtMachInst _machInst,
777544SN/A                const char * instMnem, uint64_t setFlags,
7810688Sandreas.hansson@arm.com                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
7910688Sandreas.hansson@arm.com                uint64_t _disp, InstRegIndex _segment,
8010688Sandreas.hansson@arm.com                InstRegIndex _data,
817544SN/A                uint8_t _dataSize, uint8_t _addressSize,
823262SN/A                Request::FlagsType _memFlags);
8310688Sandreas.hansson@arm.com
843262SN/A        %(BasicExecDeclare)s
853262SN/A    };
865034SN/A}};
8713892Sgabeblack@google.com
8812085Sspwilson2@wisc.edu// Load templates
8912085Sspwilson2@wisc.edu
9012085Sspwilson2@wisc.edudef template MicroLoadExecute {{
9110688Sandreas.hansson@arm.com    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
9210688Sandreas.hansson@arm.com          Trace::InstRecord *traceData) const
9310688Sandreas.hansson@arm.com    {
9410688Sandreas.hansson@arm.com        Fault fault = NoFault;
955034SN/A        Addr EA;
965034SN/A
975034SN/A        %(op_decl)s;
9812680Sgiacomo.travaglini@arm.com        %(op_rd)s;
9910688Sandreas.hansson@arm.com        %(ea_code)s;
10010688Sandreas.hansson@arm.com        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
1015034SN/A
10210688Sandreas.hansson@arm.com        fault = readMemAtomic(xc, traceData, EA, Mem,
1035034SN/A                              %(memDataSize)s, memFlags);
1045034SN/A
10510688Sandreas.hansson@arm.com        if (fault == NoFault) {
10610688Sandreas.hansson@arm.com            %(code)s;
1072SN/A        } else if (memFlags & Request::PREFETCH) {
1087544SN/A            // For prefetches, ignore any faults/exceptions.
10910688Sandreas.hansson@arm.com            return NoFault;
11010688Sandreas.hansson@arm.com        }
1117544SN/A        if(fault == NoFault)
1122SN/A        {
1132SN/A            %(op_wb)s;
1142SN/A        }
1152SN/A
1162SN/A        return fault;
1172SN/A    }
1188436SBrad.Beckmann@amd.com}};
1191298SN/A
12010688Sandreas.hansson@arm.comdef template MicroLoadInitiateAcc {{
12110688Sandreas.hansson@arm.com    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
12210688Sandreas.hansson@arm.com            Trace::InstRecord * traceData) const
1233187SN/A    {
1243187SN/A        Fault fault = NoFault;
12513784Sgabeblack@google.com        Addr EA;
12613784Sgabeblack@google.com
1273187SN/A        %(op_decl)s;
12810688Sandreas.hansson@arm.com        %(op_rd)s;
12910688Sandreas.hansson@arm.com        %(ea_code)s;
1303187SN/A        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
13113892Sgabeblack@google.com
1323187SN/A        fault = initiateMemRead(xc, traceData, EA,
1333187SN/A                                %(memDataSize)s, memFlags);
1343187SN/A
13510688Sandreas.hansson@arm.com        return fault;
1362SN/A    }
13712749Sgiacomo.travaglini@arm.com}};
13810688Sandreas.hansson@arm.com
1394628SN/Adef template MicroLoadCompleteAcc {{
14010688Sandreas.hansson@arm.com    Fault %(class_name)s::completeAcc(PacketPtr pkt,
14110688Sandreas.hansson@arm.com            CPU_EXEC_CONTEXT * xc,
14210688Sandreas.hansson@arm.com            Trace::InstRecord * traceData) const
14310688Sandreas.hansson@arm.com    {
1447544SN/A        Fault fault = NoFault;
14510688Sandreas.hansson@arm.com
1464628SN/A        %(op_decl)s;
14710688Sandreas.hansson@arm.com        %(op_rd)s;
1488436SBrad.Beckmann@amd.com
1494628SN/A        getMem(pkt, Mem, %(memDataSize)s, traceData);
15010688Sandreas.hansson@arm.com
1511298SN/A        %(code)s;
1528436SBrad.Beckmann@amd.com
15310688Sandreas.hansson@arm.com        if(fault == NoFault)
15410688Sandreas.hansson@arm.com        {
15510688Sandreas.hansson@arm.com            %(op_wb)s;
1562SN/A        }
1578436SBrad.Beckmann@amd.com
1588436SBrad.Beckmann@amd.com        return fault;
15910688Sandreas.hansson@arm.com    }
16010688Sandreas.hansson@arm.com}};
1618436SBrad.Beckmann@amd.com
1628436SBrad.Beckmann@amd.com// Store templates
16310688Sandreas.hansson@arm.com
16410688Sandreas.hansson@arm.comdef template MicroStoreExecute {{
1658436SBrad.Beckmann@amd.com    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT * xc,
1662SN/A            Trace::InstRecord *traceData) const
1678436SBrad.Beckmann@amd.com    {
1688436SBrad.Beckmann@amd.com        Fault fault = NoFault;
1692SN/A
1708436SBrad.Beckmann@amd.com        Addr EA;
1718436SBrad.Beckmann@amd.com        %(op_decl)s;
1728436SBrad.Beckmann@amd.com        %(op_rd)s;
1738436SBrad.Beckmann@amd.com        %(ea_code)s;
1748436SBrad.Beckmann@amd.com        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
1758436SBrad.Beckmann@amd.com
1768436SBrad.Beckmann@amd.com        %(code)s;
1778436SBrad.Beckmann@amd.com
1788436SBrad.Beckmann@amd.com        if(fault == NoFault)
1798436SBrad.Beckmann@amd.com        {
18010688Sandreas.hansson@arm.com            fault = writeMemAtomic(xc, traceData, Mem, %(memDataSize)s, EA,
18110688Sandreas.hansson@arm.com                    memFlags, NULL);
18210688Sandreas.hansson@arm.com            if(fault == NoFault)
1838436SBrad.Beckmann@amd.com            {
1848436SBrad.Beckmann@amd.com                %(op_wb)s;
1852SN/A            }
1862SN/A        }
1872SN/A
18810688Sandreas.hansson@arm.com        return fault;
1893187SN/A    }
19010688Sandreas.hansson@arm.com}};
19114027Stiago.muck@arm.com
19214027Stiago.muck@arm.comdef template MicroStoreInitiateAcc {{
19314027Stiago.muck@arm.com    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
19414027Stiago.muck@arm.com            Trace::InstRecord * traceData) const
19514027Stiago.muck@arm.com    {
19614027Stiago.muck@arm.com        Fault fault = NoFault;
1972SN/A
1982SN/A        Addr EA;
1992SN/A        %(op_decl)s;
2002SN/A        %(op_rd)s;
2012SN/A        %(ea_code)s;
20213892Sgabeblack@google.com        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
20311523Sdavid.guillen@arm.com
204729SN/A        %(code)s;
2052SN/A
206695SN/A        if(fault == NoFault)
2072SN/A        {
2082SN/A            fault = writeMemTiming(xc, traceData, Mem, %(memDataSize)s, EA,
2092SN/A                    memFlags, NULL);
2102SN/A        }
211695SN/A        return fault;
2122SN/A    }
2132SN/A}};
2142SN/A
2152SN/Adef template MicroStoreCompleteAcc {{
2162SN/A    Fault %(class_name)s::completeAcc(PacketPtr pkt,
2172SN/A            CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const
2182SN/A    {
2192SN/A        %(op_decl)s;
22010688Sandreas.hansson@arm.com        %(op_rd)s;
22110688Sandreas.hansson@arm.com        %(complete_code)s;
2222SN/A        %(op_wb)s;
22310688Sandreas.hansson@arm.com        return NoFault;
22410348Sandreas.hansson@arm.com    }
22510688Sandreas.hansson@arm.com}};
22610688Sandreas.hansson@arm.com
22710348Sandreas.hansson@arm.com// Common templates
2285736SN/A
2293187SN/A//This delcares the initiateAcc function in memory operations
2302SN/Adef template InitiateAccDeclare {{
23110688Sandreas.hansson@arm.com    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
23210688Sandreas.hansson@arm.com}};
23310688Sandreas.hansson@arm.com
2349301Snilay@cs.wisc.edu//This declares the completeAcc function in memory operations
23510688Sandreas.hansson@arm.comdef template CompleteAccDeclare {{
23610688Sandreas.hansson@arm.com    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
23710688Sandreas.hansson@arm.com}};
23810688Sandreas.hansson@arm.com
23910688Sandreas.hansson@arm.comdef template MicroLdStOpDeclare {{
24010688Sandreas.hansson@arm.com    class %(class_name)s : public %(base_class)s
24110688Sandreas.hansson@arm.com    {
24210688Sandreas.hansson@arm.com      public:
24310688Sandreas.hansson@arm.com        %(class_name)s(ExtMachInst _machInst,
24410688Sandreas.hansson@arm.com                const char * instMnem, uint64_t setFlags,
24510688Sandreas.hansson@arm.com                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
2469301Snilay@cs.wisc.edu                uint64_t _disp, InstRegIndex _segment,
24710348Sandreas.hansson@arm.com                InstRegIndex _data,
24810348Sandreas.hansson@arm.com                uint8_t _dataSize, uint8_t _addressSize,
24912749Sgiacomo.travaglini@arm.com                Request::FlagsType _memFlags);
25011435Smitch.hayenga@arm.com
2512SN/A        %(BasicExecDeclare)s
25210688Sandreas.hansson@arm.com
25310688Sandreas.hansson@arm.com        %(InitiateAccDeclare)s
25410688Sandreas.hansson@arm.com
25510688Sandreas.hansson@arm.com        %(CompleteAccDeclare)s
25610688Sandreas.hansson@arm.com    };
25710688Sandreas.hansson@arm.com}};
25810688Sandreas.hansson@arm.com
25910688Sandreas.hansson@arm.com// LdStSplitOp is a load or store that uses a pair of regs as the
2603187SN/A// source or destination.  Used for cmpxchg{8,16}b.
2612SN/Adef template MicroLdStSplitOpDeclare {{
26210688Sandreas.hansson@arm.com    class %(class_name)s : public %(base_class)s
26310688Sandreas.hansson@arm.com    {
26410688Sandreas.hansson@arm.com      public:
26510688Sandreas.hansson@arm.com        %(class_name)s(ExtMachInst _machInst,
26610688Sandreas.hansson@arm.com                const char * instMnem, uint64_t setFlags,
26710688Sandreas.hansson@arm.com                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
26810688Sandreas.hansson@arm.com                uint64_t _disp, InstRegIndex _segment,
26910688Sandreas.hansson@arm.com                InstRegIndex _dataLow, InstRegIndex _dataHi,
27010688Sandreas.hansson@arm.com                uint8_t _dataSize, uint8_t _addressSize,
2713187SN/A                Request::FlagsType _memFlags);
2724628SN/A
27310688Sandreas.hansson@arm.com        %(BasicExecDeclare)s
27410688Sandreas.hansson@arm.com
27510688Sandreas.hansson@arm.com        %(InitiateAccDeclare)s
2763187SN/A
27710688Sandreas.hansson@arm.com        %(CompleteAccDeclare)s
27810688Sandreas.hansson@arm.com    };
27910688Sandreas.hansson@arm.com}};
28010688Sandreas.hansson@arm.com
28110688Sandreas.hansson@arm.comdef template MicroLdStOpConstructor {{
28210688Sandreas.hansson@arm.com    %(class_name)s::%(class_name)s(
2833187SN/A            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
28410688Sandreas.hansson@arm.com            uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
28510688Sandreas.hansson@arm.com            uint64_t _disp, InstRegIndex _segment,
28610688Sandreas.hansson@arm.com            InstRegIndex _data,
28710688Sandreas.hansson@arm.com            uint8_t _dataSize, uint8_t _addressSize,
28810688Sandreas.hansson@arm.com            Request::FlagsType _memFlags) :
28910688Sandreas.hansson@arm.com        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
29010688Sandreas.hansson@arm.com                _scale, _index, _base,
29110688Sandreas.hansson@arm.com                _disp, _segment, _data,
29210688Sandreas.hansson@arm.com                _dataSize, _addressSize, _memFlags, %(op_class)s)
29310688Sandreas.hansson@arm.com    {
29410688Sandreas.hansson@arm.com        %(constructor)s;
2953187SN/A    }
29610688Sandreas.hansson@arm.com}};
29710688Sandreas.hansson@arm.com
2981298SN/Adef template MicroLdStSplitOpConstructor {{
29910688Sandreas.hansson@arm.com    %(class_name)s::%(class_name)s(
30010688Sandreas.hansson@arm.com            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
30110688Sandreas.hansson@arm.com            uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
3024628SN/A            uint64_t _disp, InstRegIndex _segment,
30310688Sandreas.hansson@arm.com            InstRegIndex _dataLow, InstRegIndex _dataHi,
30410688Sandreas.hansson@arm.com            uint8_t _dataSize, uint8_t _addressSize,
30510688Sandreas.hansson@arm.com            Request::FlagsType _memFlags) :
30610688Sandreas.hansson@arm.com        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
30710688Sandreas.hansson@arm.com                _scale, _index, _base,
3083187SN/A                _disp, _segment, _dataLow, _dataHi,
30914027Stiago.muck@arm.com                _dataSize, _addressSize, _memFlags, %(op_class)s)
31014027Stiago.muck@arm.com    {
31114027Stiago.muck@arm.com        %(constructor)s;
31214027Stiago.muck@arm.com    }
3132SN/A}};
3142SN/A
3152SN/Alet {{
31610688Sandreas.hansson@arm.com    class LdStOp(X86Microop):
3172SN/A        def __init__(self, data, segment, addr, disp,
31810688Sandreas.hansson@arm.com                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
31910688Sandreas.hansson@arm.com                implicitStack):
32010688Sandreas.hansson@arm.com            self.data = data
32110688Sandreas.hansson@arm.com            [self.scale, self.index, self.base] = addr
32210688Sandreas.hansson@arm.com            self.disp = disp
32310688Sandreas.hansson@arm.com            self.segment = segment
32410688Sandreas.hansson@arm.com            self.dataSize = dataSize
32510688Sandreas.hansson@arm.com            self.addressSize = addressSize
32610688Sandreas.hansson@arm.com            self.memFlags = baseFlags
32710688Sandreas.hansson@arm.com            if atCPL0:
32810688Sandreas.hansson@arm.com                self.memFlags += " | (CPL0FlagBit << FlagShift)"
32910688Sandreas.hansson@arm.com            self.instFlags = ""
33010688Sandreas.hansson@arm.com            if prefetch:
33110688Sandreas.hansson@arm.com                self.memFlags += " | Request::PREFETCH"
33210688Sandreas.hansson@arm.com                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
33310688Sandreas.hansson@arm.com            if nonSpec:
33410688Sandreas.hansson@arm.com                self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
33510688Sandreas.hansson@arm.com            # For implicit stack operations, we should use *not* use the
33610688Sandreas.hansson@arm.com            # alternative addressing mode for loads/stores if the prefix is set
33714027Stiago.muck@arm.com            if not implicitStack:
3383187SN/A                self.memFlags += " | (machInst.legacy.addr ? " + \
3392SN/A                                 "(AddrSizeFlagBit << FlagShift) : 0)"
3402SN/A
3415315SN/A        def getAllocator(self, microFlags):
3425315SN/A            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
3435315SN/A                    %(flags)s, %(scale)s, %(index)s, %(base)s,
3445315SN/A                    %(disp)s, %(segment)s, %(data)s,
3455315SN/A                    %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
346                "class_name" : self.className,
347                "flags" : self.microFlagsText(microFlags) + self.instFlags,
348                "scale" : self.scale, "index" : self.index,
349                "base" : self.base,
350                "disp" : self.disp,
351                "segment" : self.segment, "data" : self.data,
352                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
353                "memFlags" : self.memFlags}
354            return allocator
355
356    class BigLdStOp(X86Microop):
357        def __init__(self, data, segment, addr, disp,
358                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
359                implicitStack):
360            self.data = data
361            [self.scale, self.index, self.base] = addr
362            self.disp = disp
363            self.segment = segment
364            self.dataSize = dataSize
365            self.addressSize = addressSize
366            self.memFlags = baseFlags
367            if atCPL0:
368                self.memFlags += " | (CPL0FlagBit << FlagShift)"
369            self.instFlags = ""
370            if prefetch:
371                self.memFlags += " | Request::PREFETCH"
372                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
373            if nonSpec:
374                self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
375            # For implicit stack operations, we should use *not* use the
376            # alternative addressing mode for loads/stores if the prefix is set
377            if not implicitStack:
378                self.memFlags += " | (machInst.legacy.addr ? " + \
379                                 "(AddrSizeFlagBit << FlagShift) : 0)"
380
381        def getAllocator(self, microFlags):
382            allocString = '''
383                (%(dataSize)s >= 4) ?
384                    (StaticInstPtr)(new %(class_name)sBig(machInst,
385                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
386                        %(base)s, %(disp)s, %(segment)s, %(data)s,
387                        %(dataSize)s, %(addressSize)s, %(memFlags)s)) :
388                    (StaticInstPtr)(new %(class_name)s(machInst,
389                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
390                        %(base)s, %(disp)s, %(segment)s, %(data)s,
391                        %(dataSize)s, %(addressSize)s, %(memFlags)s))
392            '''
393            allocator = allocString % {
394                "class_name" : self.className,
395                "flags" : self.microFlagsText(microFlags) + self.instFlags,
396                "scale" : self.scale, "index" : self.index,
397                "base" : self.base,
398                "disp" : self.disp,
399                "segment" : self.segment, "data" : self.data,
400                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
401                "memFlags" : self.memFlags}
402            return allocator
403
404    class LdStSplitOp(LdStOp):
405        def __init__(self, data, segment, addr, disp,
406                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
407                implicitStack):
408            super(LdStSplitOp, self).__init__(0, segment, addr, disp,
409                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
410                implicitStack)
411            (self.dataLow, self.dataHi) = data
412
413        def getAllocator(self, microFlags):
414            allocString = '''(StaticInstPtr)(new %(class_name)s(machInst,
415                        macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
416                        %(base)s, %(disp)s, %(segment)s,
417                        %(dataLow)s, %(dataHi)s,
418                        %(dataSize)s, %(addressSize)s, %(memFlags)s))
419            '''
420            allocator = allocString % {
421                "class_name" : self.className,
422                "flags" : self.microFlagsText(microFlags) + self.instFlags,
423                "scale" : self.scale, "index" : self.index,
424                "base" : self.base,
425                "disp" : self.disp,
426                "segment" : self.segment,
427                "dataLow" : self.dataLow, "dataHi" : self.dataHi,
428                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
429                "memFlags" : self.memFlags}
430            return allocator
431
432}};
433
434let {{
435
436    # Make these empty strings so that concatenating onto
437    # them will always work.
438    header_output = ""
439    decoder_output = ""
440    exec_output = ""
441
442    segmentEAExpr = \
443        'bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);'
444
445    calculateEA = 'EA = SegBase + ' + segmentEAExpr
446
447    def defineMicroLoadOp(mnemonic, code, bigCode='',
448                          mem_flags="0", big=True, nonSpec=False,
449                          implicitStack=False):
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        iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
459                              { "code": code,
460                                "ea_code": calculateEA,
461                                "memDataSize": "dataSize" })]
462        if big:
463            iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
464                                   { "code": bigCode,
465                                     "ea_code": calculateEA,
466                                     "memDataSize": "dataSize" })]
467        for iop in iops:
468            header_output += MicroLdStOpDeclare.subst(iop)
469            decoder_output += MicroLdStOpConstructor.subst(iop)
470            exec_output += MicroLoadExecute.subst(iop)
471            exec_output += MicroLoadInitiateAcc.subst(iop)
472            exec_output += MicroLoadCompleteAcc.subst(iop)
473
474        if implicitStack:
475            # For instructions that implicitly access the stack, the address
476            # size is the same as the stack segment pointer size, not the
477            # address size if specified by the instruction prefix
478            addressSize = "env.stackSize"
479        else:
480            addressSize = "env.addressSize"
481
482        base = LdStOp
483        if big:
484            base = BigLdStOp
485        class LoadOp(base):
486            def __init__(self, data, segment, addr, disp = 0,
487                    dataSize="env.dataSize",
488                    addressSize=addressSize,
489                    atCPL0=False, prefetch=False, nonSpec=nonSpec,
490                    implicitStack=implicitStack):
491                super(LoadOp, self).__init__(data, segment, addr,
492                        disp, dataSize, addressSize, mem_flags,
493                        atCPL0, prefetch, nonSpec, implicitStack)
494                self.className = Name
495                self.mnemonic = name
496
497        microopClasses[name] = LoadOp
498
499    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);',
500                            'Data = Mem & mask(dataSize * 8);')
501    defineMicroLoadOp('Ldis', 'Data = merge(Data, Mem, dataSize);',
502                              'Data = Mem & mask(dataSize * 8);',
503                               implicitStack=True)
504    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
505                              'Data = Mem & mask(dataSize * 8);',
506                      '(StoreCheck << FlagShift)')
507    defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
508                               'Data = Mem & mask(dataSize * 8);',
509                      '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
510                      nonSpec=True)
511
512    defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False)
513
514    defineMicroLoadOp('Ldfp87', code='''
515        switch (dataSize)
516        {
517          case 4:
518            FpData_df = *(float *)&Mem;
519            break;
520          case 8:
521            FpData_df = *(double *)&Mem;
522            break;
523          default:
524            panic("Unhandled data size in LdFp87.\\n");
525        }
526    ''', big = False)
527
528    # Load integer from memory into x87 top-of-stack register.
529    # Used to implement fild instruction.
530    defineMicroLoadOp('Ldifp87', code='''
531        switch (dataSize)
532        {
533          case 2:
534            FpData_df = (int64_t)sext<16>(Mem);
535            break;
536          case 4:
537            FpData_df = (int64_t)sext<32>(Mem);
538            break;
539          case 8:
540            FpData_df = (int64_t)Mem;
541            break;
542          default:
543            panic("Unhandled data size in LdIFp87.\\n");
544        }
545    ''', big = False)
546
547    def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False):
548        global header_output
549        global decoder_output
550        global exec_output
551        global microopClasses
552        Name = mnemonic
553        name = mnemonic.lower()
554
555        iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
556                            { "code": code,
557                              "ea_code": calculateEA,
558                              "memDataSize": "2 * dataSize" })
559
560        header_output += MicroLdStSplitOpDeclare.subst(iop)
561        decoder_output += MicroLdStSplitOpConstructor.subst(iop)
562        exec_output += MicroLoadExecute.subst(iop)
563        exec_output += MicroLoadInitiateAcc.subst(iop)
564        exec_output += MicroLoadCompleteAcc.subst(iop)
565
566        class LoadOp(LdStSplitOp):
567            def __init__(self, data, segment, addr, disp = 0,
568                    dataSize="env.dataSize",
569                    addressSize="env.addressSize",
570                    atCPL0=False, prefetch=False, nonSpec=nonSpec,
571                    implicitStack=False):
572                super(LoadOp, self).__init__(data, segment, addr,
573                        disp, dataSize, addressSize, mem_flags,
574                        atCPL0, prefetch, nonSpec, implicitStack)
575                self.className = Name
576                self.mnemonic = name
577
578        microopClasses[name] = LoadOp
579
580    code = '''
581        switch (dataSize) {
582          case 4:
583            DataLow = bits(Mem_u2qw[0], 31, 0);
584            DataHi  = bits(Mem_u2qw[0], 63, 32);
585            break;
586          case 8:
587            DataLow = Mem_u2qw[0];
588            DataHi  = Mem_u2qw[1];
589            break;
590          default:
591            panic("Unhandled data size %d in LdSplit.\\n", dataSize);
592        }'''
593
594    defineMicroLoadSplitOp('LdSplit', code,
595                           '(StoreCheck << FlagShift)')
596
597    defineMicroLoadSplitOp('LdSplitl', code,
598                           '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
599                           nonSpec=True)
600
601    def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0",
602                           implicitStack=False):
603        global header_output
604        global decoder_output
605        global exec_output
606        global microopClasses
607        Name = mnemonic
608        name = mnemonic.lower()
609
610        # Build up the all register version of this micro op
611        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
612                            { "code": code,
613                              "complete_code": completeCode,
614                              "ea_code": calculateEA,
615                              "memDataSize": "dataSize" })
616        header_output += MicroLdStOpDeclare.subst(iop)
617        decoder_output += MicroLdStOpConstructor.subst(iop)
618        exec_output += MicroStoreExecute.subst(iop)
619        exec_output += MicroStoreInitiateAcc.subst(iop)
620        exec_output += MicroStoreCompleteAcc.subst(iop)
621
622        if implicitStack:
623            # For instructions that implicitly access the stack, the address
624            # size is the same as the stack segment pointer size, not the
625            # address size if specified by the instruction prefix
626            addressSize = "env.stackSize"
627        else:
628            addressSize = "env.addressSize"
629
630        class StoreOp(LdStOp):
631            def __init__(self, data, segment, addr, disp = 0,
632                    dataSize="env.dataSize",
633                    addressSize=addressSize,
634                    atCPL0=False, nonSpec=False, implicitStack=implicitStack):
635                super(StoreOp, self).__init__(data, segment, addr, disp,
636                        dataSize, addressSize, mem_flags, atCPL0, False,
637                        nonSpec, implicitStack)
638                self.className = Name
639                self.mnemonic = name
640
641        microopClasses[name] = StoreOp
642
643    defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
644    defineMicroStoreOp('Stis', 'Mem = pick(Data, 2, dataSize);',
645                       implicitStack=True)
646    defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
647            mem_flags="Request::LOCKED_RMW")
648
649    defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;')
650
651    defineMicroStoreOp('Stfp87', code='''
652        switch (dataSize)
653        {
654          case 4: {
655            float single(FpData_df);
656            Mem = *(uint32_t *)&single;
657          } break;
658          case 8:
659            Mem = *(uint64_t *)&FpData_df;
660            break;
661          default:
662            panic("Unhandled data size in StFp87.\\n");
663        }
664    ''')
665
666    defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
667
668    def defineMicroStoreSplitOp(mnemonic, code,
669                                completeCode="", mem_flags="0"):
670        global header_output
671        global decoder_output
672        global exec_output
673        global microopClasses
674        Name = mnemonic
675        name = mnemonic.lower()
676
677        iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
678                            { "code": code,
679                              "complete_code": completeCode,
680                              "ea_code": calculateEA,
681                              "memDataSize": "2 * dataSize" })
682
683        header_output += MicroLdStSplitOpDeclare.subst(iop)
684        decoder_output += MicroLdStSplitOpConstructor.subst(iop)
685        exec_output += MicroStoreExecute.subst(iop)
686        exec_output += MicroStoreInitiateAcc.subst(iop)
687        exec_output += MicroStoreCompleteAcc.subst(iop)
688
689        class StoreOp(LdStSplitOp):
690            def __init__(self, data, segment, addr, disp = 0,
691                    dataSize="env.dataSize",
692                    addressSize="env.addressSize",
693                    atCPL0=False, nonSpec=False, implicitStack=False):
694                super(StoreOp, self).__init__(data, segment, addr, disp,
695                        dataSize, addressSize, mem_flags, atCPL0, False,
696                        nonSpec, implicitStack)
697                self.className = Name
698                self.mnemonic = name
699
700        microopClasses[name] = StoreOp
701
702    code = '''
703        switch (dataSize) {
704          case 4:
705            Mem_u2qw[0] = (DataHi << 32) | DataLow;
706            break;
707          case 8:
708            Mem_u2qw[0] = DataLow;
709            Mem_u2qw[1] = DataHi;
710            break;
711          default:
712            panic("Unhandled data size %d in StSplit.\\n", dataSize);
713        }'''
714
715    defineMicroStoreSplitOp('StSplit', code);
716
717    defineMicroStoreSplitOp('StSplitul', code,
718                            mem_flags='Request::LOCKED_RMW')
719
720    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
721                        { "code": "Data = merge(Data, EA, dataSize);",
722                          "ea_code": "EA = " + segmentEAExpr,
723                          "memDataSize": "dataSize" })
724    header_output += MicroLeaDeclare.subst(iop)
725    decoder_output += MicroLdStOpConstructor.subst(iop)
726    exec_output += MicroLeaExecute.subst(iop)
727
728    class LeaOp(LdStOp):
729        def __init__(self, data, segment, addr, disp = 0,
730                dataSize="env.dataSize", addressSize="env.addressSize"):
731            super(LeaOp, self).__init__(data, segment, addr, disp,
732                    dataSize, addressSize, "0", False, False, False, False)
733            self.className = "Lea"
734            self.mnemonic = "lea"
735
736    microopClasses["lea"] = LeaOp
737
738
739    iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
740                        { "code": "xc->demapPage(EA, 0);",
741                          "ea_code": calculateEA,
742                          "memDataSize": "dataSize" })
743    header_output += MicroLeaDeclare.subst(iop)
744    decoder_output += MicroLdStOpConstructor.subst(iop)
745    exec_output += MicroLeaExecute.subst(iop)
746
747    class TiaOp(LdStOp):
748        def __init__(self, segment, addr, disp = 0,
749                dataSize="env.dataSize",
750                addressSize="env.addressSize"):
751            super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
752                    addr, disp, dataSize, addressSize, "0", False, False,
753                    False, False)
754            self.className = "Tia"
755            self.mnemonic = "tia"
756
757    microopClasses["tia"] = TiaOp
758
759    class CdaOp(LdStOp):
760        def __init__(self, segment, addr, disp = 0,
761                dataSize="env.dataSize",
762                addressSize="env.addressSize", atCPL0=False):
763            super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
764                    addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
765                    atCPL0, False, False, False)
766            self.className = "Cda"
767            self.mnemonic = "cda"
768
769    microopClasses["cda"] = CdaOp
770}};
771