macromem.cc revision 10199
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2010-2013 ARM Limited
310796Sbrandon.potter@amd.com * All rights reserved
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * The license below extends only to copyright in the software and shall
610027SChris.Adeniyi-Jones@arm.com * not be construed as granting a license to any other intellectual
710027SChris.Adeniyi-Jones@arm.com * property including but not limited to intellectual property relating
810027SChris.Adeniyi-Jones@arm.com * to a hardware implementation of the functionality of the software
910027SChris.Adeniyi-Jones@arm.com * licensed hereunder.  You may use the software subject to the license
1010027SChris.Adeniyi-Jones@arm.com * terms below provided that you ensure that this notice is replicated
1110027SChris.Adeniyi-Jones@arm.com * unmodified and in its entirety in all distributions of the software,
1210027SChris.Adeniyi-Jones@arm.com * modified or unmodified, in source code or in binary form.
1310027SChris.Adeniyi-Jones@arm.com *
1410027SChris.Adeniyi-Jones@arm.com * Copyright (c) 2007-2008 The Florida State University
151458SN/A * All rights reserved.
16360SN/A *
17360SN/A * Redistribution and use in source and binary forms, with or without
18360SN/A * modification, are permitted provided that the following conditions are
19360SN/A * met: redistributions of source code must retain the above copyright
20360SN/A * notice, this list of conditions and the following disclaimer;
21360SN/A * redistributions in binary form must reproduce the above copyright
22360SN/A * notice, this list of conditions and the following disclaimer in the
23360SN/A * documentation and/or other materials provided with the distribution;
24360SN/A * neither the name of the copyright holders nor the names of its
25360SN/A * contributors may be used to endorse or promote products derived from
26360SN/A * this software without specific prior written permission.
27360SN/A *
28360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39360SN/A *
402665Ssaidi@eecs.umich.edu * Authors: Stephen Hines
412665Ssaidi@eecs.umich.edu */
422665Ssaidi@eecs.umich.edu
43360SN/A#include <sstream>
44360SN/A
451354SN/A#include "arch/arm/insts/macromem.hh"
461354SN/A
47360SN/A#include "arch/arm/generated/decoder.hh"
4812018Sandreas.sandberg@arm.com#include "arch/arm/insts/neon64_mem.hh"
4912018Sandreas.sandberg@arm.com
5012018Sandreas.sandberg@arm.comusing namespace std;
5112018Sandreas.sandberg@arm.comusing namespace ArmISAInst;
5212018Sandreas.sandberg@arm.com
5312018Sandreas.sandberg@arm.comnamespace ArmISA
5412018Sandreas.sandberg@arm.com{
552064SN/A
5612018Sandreas.sandberg@arm.comMacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
5712018Sandreas.sandberg@arm.com                       OpClass __opClass, IntRegIndex rn,
5812018Sandreas.sandberg@arm.com                       bool index, bool up, bool user, bool writeback,
5912018Sandreas.sandberg@arm.com                       bool load, uint32_t reglist) :
6012018Sandreas.sandberg@arm.com    PredMacroOp(mnem, machInst, __opClass)
6112018Sandreas.sandberg@arm.com{
6211799Sbrandon.potter@amd.com    uint32_t regs = reglist;
6312018Sandreas.sandberg@arm.com    uint32_t ones = number_of_ones(reglist);
6412018Sandreas.sandberg@arm.com    // Remember that writeback adds a uop or two and the temp register adds one
6512018Sandreas.sandberg@arm.com    numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1;
6612018Sandreas.sandberg@arm.com
6712018Sandreas.sandberg@arm.com    // It's technically legal to do a lot of nothing
6812018Sandreas.sandberg@arm.com    if (!ones)
6911799Sbrandon.potter@amd.com        numMicroops = 1;
70360SN/A
71360SN/A    microOps = new StaticInstPtr[numMicroops];
72360SN/A    uint32_t addr = 0;
73360SN/A
74360SN/A    if (!up)
75360SN/A        addr = (ones << 2) - 4;
761809SN/A
7711800Sbrandon.potter@amd.com    if (!index)
7811392Sbrandon.potter@amd.com        addr += 4;
791809SN/A
8011392Sbrandon.potter@amd.com    StaticInstPtr *uop = microOps;
8111383Sbrandon.potter@amd.com
823113Sgblack@eecs.umich.edu    // Add 0 to Rn and stick it in ureg0.
8311799Sbrandon.potter@amd.com    // This is equivalent to a move.
8411759Sbrandon.potter@amd.com    *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
8511812Sbaz21@cam.ac.uk
8611812Sbaz21@cam.ac.uk    unsigned reg = 0;
8711799Sbrandon.potter@amd.com    unsigned regIdx = 0;
888229Snate@binkert.org    bool force_user = user & !bits(reglist, 15);
898229Snate@binkert.org    bool exception_ret = user & bits(reglist, 15);
9011594Santhony.gutierrez@amd.com
917075Snate@binkert.org    for (int i = 0; i < ones; i++) {
928229Snate@binkert.org        // Find the next register.
9311856Sbrandon.potter@amd.com        while (!bits(regs, reg))
947075Snate@binkert.org            reg++;
95360SN/A        replaceBits(regs, reg, 0);
9611886Sbrandon.potter@amd.com
9711800Sbrandon.potter@amd.com        regIdx = reg;
9811392Sbrandon.potter@amd.com        if (force_user) {
992462SN/A            regIdx = intRegInMode(MODE_USER, regIdx);
1001354SN/A        }
1016216Snate@binkert.org
1026658Snate@binkert.org        if (load) {
1032474SN/A            if (writeback && i == ones - 1) {
1042680Sktlim@umich.edu                // If it's a writeback and this is the last register
1058229Snate@binkert.org                // do the load into a temporary register which we'll move
10611886Sbrandon.potter@amd.com                // into the final one later
10710496Ssteve.reinhardt@amd.com                *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0,
10811911SBrandon.Potter@amd.com                        up, addr);
1098229Snate@binkert.org            } else {
11011794Sbrandon.potter@amd.com                // Otherwise just do it normally
11111886Sbrandon.potter@amd.com                if (reg == INTREG_PC && exception_ret) {
11210497Ssteve.reinhardt@amd.com                    // This must be the exception return form of ldm.
11311794Sbrandon.potter@amd.com                    *++uop = new MicroLdrRetUop(machInst, regIdx,
114360SN/A                                               INTREG_UREG0, up, addr);
115360SN/A                    if (!(condCode == COND_AL || condCode == COND_UC))
116360SN/A                        (*uop)->setFlag(StaticInst::IsCondControl);
117360SN/A                    else
118360SN/A                        (*uop)->setFlag(StaticInst::IsUncondControl);
119360SN/A                } else {
120360SN/A                    *++uop = new MicroLdrUop(machInst, regIdx,
121360SN/A                                            INTREG_UREG0, up, addr);
122360SN/A                    if (reg == INTREG_PC) {
123360SN/A                        (*uop)->setFlag(StaticInst::IsControl);
124378SN/A                        if (!(condCode == COND_AL || condCode == COND_UC))
1251706SN/A                            (*uop)->setFlag(StaticInst::IsCondControl);
12611851Sbrandon.potter@amd.com                        else
127378SN/A                            (*uop)->setFlag(StaticInst::IsUncondControl);
128378SN/A                        (*uop)->setFlag(StaticInst::IsIndirectControl);
129378SN/A                    }
130378SN/A                }
131378SN/A            }
1321706SN/A        } else {
13311851Sbrandon.potter@amd.com            *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
134360SN/A        }
13511760Sbrandon.potter@amd.com
13611760Sbrandon.potter@amd.com        if (up)
13711851Sbrandon.potter@amd.com            addr += 4;
13811760Sbrandon.potter@amd.com        else
1396109Ssanchezd@stanford.edu            addr -= 4;
1401706SN/A    }
14111851Sbrandon.potter@amd.com
142378SN/A    if (writeback && ones) {
1436109Ssanchezd@stanford.edu        // put the register update after we're done all loading
1446109Ssanchezd@stanford.edu        if (up)
14511851Sbrandon.potter@amd.com            *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4);
1466109Ssanchezd@stanford.edu        else
14711886Sbrandon.potter@amd.com            *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4);
14811886Sbrandon.potter@amd.com
14911886Sbrandon.potter@amd.com        // If this was a load move the last temporary value into place
15011886Sbrandon.potter@amd.com        // this way we can't take an exception after we update the base
151378SN/A        // register.
1521706SN/A        if (load && reg == INTREG_PC && exception_ret) {
15311851Sbrandon.potter@amd.com            *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
154378SN/A            if (!(condCode == COND_AL || condCode == COND_UC))
1555748SSteve.Reinhardt@amd.com                (*uop)->setFlag(StaticInst::IsCondControl);
1565748SSteve.Reinhardt@amd.com            else
15711851Sbrandon.potter@amd.com                (*uop)->setFlag(StaticInst::IsUncondControl);
158378SN/A        } else if (load) {
159378SN/A            *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1);
1601706SN/A            if (reg == INTREG_PC) {
16111851Sbrandon.potter@amd.com                (*uop)->setFlag(StaticInst::IsControl);
162378SN/A                (*uop)->setFlag(StaticInst::IsCondControl);
16311886Sbrandon.potter@amd.com                (*uop)->setFlag(StaticInst::IsIndirectControl);
1641706SN/A                // This is created as a RAS POP
16511851Sbrandon.potter@amd.com                if (rn == INTREG_SP)
166378SN/A                    (*uop)->setFlag(StaticInst::IsReturn);
167378SN/A
1681706SN/A            }
16911851Sbrandon.potter@amd.com        }
170378SN/A    }
171378SN/A
1721706SN/A    (*uop)->setLastMicroop();
17311851Sbrandon.potter@amd.com
174378SN/A    /* Take the control flags from the last microop for the macroop */
1754118Sgblack@eecs.umich.edu    if ((*uop)->isControl())
1764118Sgblack@eecs.umich.edu        setFlag(StaticInst::IsControl);
17711851Sbrandon.potter@amd.com    if ((*uop)->isCondCtrl())
1784118Sgblack@eecs.umich.edu        setFlag(StaticInst::IsCondControl);
179378SN/A    if ((*uop)->isIndirectCtrl())
1801706SN/A        setFlag(StaticInst::IsIndirectControl);
18111851Sbrandon.potter@amd.com    if ((*uop)->isReturn())
182378SN/A        setFlag(StaticInst::IsReturn);
183378SN/A
1841706SN/A    for (StaticInstPtr *curUop = microOps;
18511851Sbrandon.potter@amd.com            !(*curUop)->isLastMicroop(); curUop++) {
186360SN/A        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
1875513SMichael.Adler@intel.com        assert(uopPtr);
1885513SMichael.Adler@intel.com        uopPtr->setDelayedCommit();
18911851Sbrandon.potter@amd.com    }
1905513SMichael.Adler@intel.com}
19110203SAli.Saidi@ARM.com
19210203SAli.Saidi@ARM.comPairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
19311851Sbrandon.potter@amd.com                     uint32_t size, bool fp, bool load, bool noAlloc,
19410203SAli.Saidi@ARM.com                     bool signExt, bool exclusive, bool acrel,
1955513SMichael.Adler@intel.com                     int64_t imm, AddrMode mode,
19611851Sbrandon.potter@amd.com                     IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) :
1975513SMichael.Adler@intel.com    PredMacroOp(mnem, machInst, __opClass)
198511SN/A{
19910633Smichaelupton@gmail.com    bool writeback = (mode != AddrMd_Offset);
20011851Sbrandon.potter@amd.com    numMicroops = 1 + (size / 4) + (writeback ? 1 : 0);
20110633Smichaelupton@gmail.com    microOps = new StaticInstPtr[numMicroops];
2021706SN/A
20311851Sbrandon.potter@amd.com    StaticInstPtr *uop = microOps;
204511SN/A
2055513SMichael.Adler@intel.com    bool post = (mode == AddrMd_PostIndex);
2065513SMichael.Adler@intel.com
20711851Sbrandon.potter@amd.com    rn = makeSP(rn);
2085513SMichael.Adler@intel.com
209511SN/A    *uop = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, post ? 0 : imm);
2101706SN/A
21111851Sbrandon.potter@amd.com    if (fp) {
2121706SN/A        if (size == 16) {
2131706SN/A            if (load) {
2141706SN/A                *++uop = new MicroLdrQBFpXImmUop(machInst, rt,
2151706SN/A                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21611851Sbrandon.potter@amd.com                *++uop = new MicroLdrQTFpXImmUop(machInst, rt,
2171706SN/A                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
2181706SN/A                *++uop = new MicroLdrQBFpXImmUop(machInst, rt2,
2191706SN/A                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
2201706SN/A                *++uop = new MicroLdrQTFpXImmUop(machInst, rt2,
22111851Sbrandon.potter@amd.com                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
2221706SN/A            } else {
223511SN/A                *++uop = new MicroStrQBFpXImmUop(machInst, rt,
2246703Svince@csl.cornell.edu                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
2256703Svince@csl.cornell.edu                *++uop = new MicroStrQTFpXImmUop(machInst, rt,
22611851Sbrandon.potter@amd.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
2276703Svince@csl.cornell.edu                *++uop = new MicroStrQBFpXImmUop(machInst, rt2,
2286685Stjones1@inf.ed.ac.uk                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
2296685Stjones1@inf.ed.ac.uk                *++uop = new MicroStrQTFpXImmUop(machInst, rt2,
23011851Sbrandon.potter@amd.com                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
2316685Stjones1@inf.ed.ac.uk            }
2326685Stjones1@inf.ed.ac.uk        } else if (size == 8) {
2335513SMichael.Adler@intel.com            if (load) {
2345513SMichael.Adler@intel.com                *++uop = new MicroLdrFpXImmUop(machInst, rt,
23511851Sbrandon.potter@amd.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
2365513SMichael.Adler@intel.com                *++uop = new MicroLdrFpXImmUop(machInst, rt2,
23711885Sbrandon.potter@amd.com                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
23811885Sbrandon.potter@amd.com            } else {
23911885Sbrandon.potter@amd.com                *++uop = new MicroStrFpXImmUop(machInst, rt,
2405513SMichael.Adler@intel.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
2411999SN/A                *++uop = new MicroStrFpXImmUop(machInst, rt2,
2421999SN/A                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
24311851Sbrandon.potter@amd.com            }
2441999SN/A        } else if (size == 4) {
24511885Sbrandon.potter@amd.com            if (load) {
24611885Sbrandon.potter@amd.com                *++uop = new MicroLdrDFpXImmUop(machInst, rt, rt2,
24711885Sbrandon.potter@amd.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
2481999SN/A            } else {
2491999SN/A                *++uop = new MicroStrDFpXImmUop(machInst, rt, rt2,
2501999SN/A                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
25111851Sbrandon.potter@amd.com            }
2521999SN/A        }
2533079Sstever@eecs.umich.edu    } else {
2543079Sstever@eecs.umich.edu        if (size == 8) {
25511851Sbrandon.potter@amd.com            if (load) {
2563079Sstever@eecs.umich.edu                *++uop = new MicroLdrXImmUop(machInst, rt, INTREG_UREG0,
25711908SBrandon.Potter@amd.com                        0, noAlloc, exclusive, acrel);
25811908SBrandon.Potter@amd.com                *++uop = new MicroLdrXImmUop(machInst, rt2, INTREG_UREG0,
25911908SBrandon.Potter@amd.com                        size, noAlloc, exclusive, acrel);
26011908SBrandon.Potter@amd.com            } else {
26111875Sbrandon.potter@amd.com                *++uop = new MicroStrXImmUop(machInst, rt, INTREG_UREG0,
2622093SN/A                        0, noAlloc, exclusive, acrel);
26311851Sbrandon.potter@amd.com                *++uop = new MicroStrXImmUop(machInst, rt2, INTREG_UREG0,
2642093SN/A                        size, noAlloc, exclusive, acrel);
2652687Sksewell@umich.edu            }
2662687Sksewell@umich.edu        } else if (size == 4) {
26711851Sbrandon.potter@amd.com            if (load) {
2682687Sksewell@umich.edu                if (signExt) {
2692238SN/A                    *++uop = new MicroLdrDSXImmUop(machInst, rt, rt2,
2702238SN/A                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27111851Sbrandon.potter@amd.com                } else {
2722238SN/A                    *++uop = new MicroLdrDUXImmUop(machInst, rt, rt2,
27311908SBrandon.Potter@amd.com                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27411908SBrandon.Potter@amd.com                }
27511908SBrandon.Potter@amd.com            } else {
27611908SBrandon.Potter@amd.com                *++uop = new MicroStrDXImmUop(machInst, rt, rt2,
27711908SBrandon.Potter@amd.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27811908SBrandon.Potter@amd.com            }
27911908SBrandon.Potter@amd.com        }
28011908SBrandon.Potter@amd.com    }
2812238SN/A
2822238SN/A    if (writeback) {
28311851Sbrandon.potter@amd.com        *++uop = new MicroAddXiUop(machInst, rn, INTREG_UREG0,
2842238SN/A                                   post ? imm : 0);
2852238SN/A    }
2862238SN/A
28711851Sbrandon.potter@amd.com    (*uop)->setLastMicroop();
2882238SN/A
2892238SN/A    for (StaticInstPtr *curUop = microOps;
2902238SN/A            !(*curUop)->isLastMicroop(); curUop++) {
29111851Sbrandon.potter@amd.com        (*curUop)->setDelayedCommit();
2922238SN/A    }
2932238SN/A}
2942238SN/A
29511851Sbrandon.potter@amd.comBigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst,
2962238SN/A                             OpClass __opClass, bool load, IntRegIndex dest,
2972238SN/A                             IntRegIndex base, int64_t imm) :
2982238SN/A    PredMacroOp(mnem, machInst, __opClass)
29911851Sbrandon.potter@amd.com{
3002238SN/A    numMicroops = 2;
3012238SN/A    microOps = new StaticInstPtr[numMicroops];
3022238SN/A
30311851Sbrandon.potter@amd.com    if (load) {
3042238SN/A        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
3059455Smitch.hayenga+gem5@gmail.com        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
3069455Smitch.hayenga+gem5@gmail.com    } else {
30711851Sbrandon.potter@amd.com        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
30810203SAli.Saidi@ARM.com        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
30911851Sbrandon.potter@amd.com    }
31011851Sbrandon.potter@amd.com    microOps[0]->setDelayedCommit();
3119455Smitch.hayenga+gem5@gmail.com    microOps[1]->setLastMicroop();
3129112Smarc.orr@gmail.com}
31311906SBrandon.Potter@amd.com
31411906SBrandon.Potter@amd.comBigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst,
3159112Smarc.orr@gmail.com                               OpClass __opClass, bool load, IntRegIndex dest,
3169112Smarc.orr@gmail.com                               IntRegIndex base, int64_t imm) :
31711851Sbrandon.potter@amd.com    PredMacroOp(mnem, machInst, __opClass)
3189112Smarc.orr@gmail.com{
3199112Smarc.orr@gmail.com    numMicroops = 3;
32011911SBrandon.Potter@amd.com    microOps = new StaticInstPtr[numMicroops];
3219112Smarc.orr@gmail.com
32211911SBrandon.Potter@amd.com    if (load) {
32311911SBrandon.Potter@amd.com        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, 0);
32411911SBrandon.Potter@amd.com        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, 0);
32511911SBrandon.Potter@amd.com    } else {
3269112Smarc.orr@gmail.com        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, 0);
32711911SBrandon.Potter@amd.com        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, 0);
32811911SBrandon.Potter@amd.com    }
32911911SBrandon.Potter@amd.com    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
33011911SBrandon.Potter@amd.com
3319238Slluc.alvarez@bsc.es    microOps[0]->setDelayedCommit();
3329112Smarc.orr@gmail.com    microOps[1]->setDelayedCommit();
33311911SBrandon.Potter@amd.com    microOps[2]->setLastMicroop();
3349112Smarc.orr@gmail.com}
33511911SBrandon.Potter@amd.com
33611911SBrandon.Potter@amd.comBigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst,
33711911SBrandon.Potter@amd.com                             OpClass __opClass, bool load, IntRegIndex dest,
33811911SBrandon.Potter@amd.com                             IntRegIndex base, int64_t imm) :
33911911SBrandon.Potter@amd.com    PredMacroOp(mnem, machInst, __opClass)
3409112Smarc.orr@gmail.com{
34111911SBrandon.Potter@amd.com    numMicroops = 3;
34211911SBrandon.Potter@amd.com    microOps = new StaticInstPtr[numMicroops];
34311911SBrandon.Potter@amd.com
34411911SBrandon.Potter@amd.com    if (load) {
34511911SBrandon.Potter@amd.com        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
34611911SBrandon.Potter@amd.com        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
3479112Smarc.orr@gmail.com    } else {
3489112Smarc.orr@gmail.com        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
34911911SBrandon.Potter@amd.com        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
35011911SBrandon.Potter@amd.com    }
3519112Smarc.orr@gmail.com    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
35211911SBrandon.Potter@amd.com
35311911SBrandon.Potter@amd.com    microOps[0]->setDelayedCommit();
3549112Smarc.orr@gmail.com    microOps[1]->setDelayedCommit();
3559112Smarc.orr@gmail.com    microOps[2]->setLastMicroop();
35611911SBrandon.Potter@amd.com}
35711911SBrandon.Potter@amd.com
3589112Smarc.orr@gmail.comBigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst,
3599112Smarc.orr@gmail.com                             OpClass __opClass, bool load, IntRegIndex dest,
3602238SN/A                             IntRegIndex base, IntRegIndex offset,
3612238SN/A                             ArmExtendType type, int64_t imm) :
3622238SN/A    PredMacroOp(mnem, machInst, __opClass)
3632238SN/A{
36411851Sbrandon.potter@amd.com    numMicroops = 2;
3652238SN/A    microOps = new StaticInstPtr[numMicroops];
3662238SN/A
3672238SN/A    if (load) {
36811851Sbrandon.potter@amd.com        microOps[0] = new MicroLdrQBFpXRegUop(machInst, dest, base,
3692238SN/A                                              offset, type, imm);
3702238SN/A        microOps[1] = new MicroLdrQTFpXRegUop(machInst, dest, base,
3712238SN/A                                              offset, type, imm);
37211851Sbrandon.potter@amd.com    } else {
3732238SN/A        microOps[0] = new MicroStrQBFpXRegUop(machInst, dest, base,
3742238SN/A                                              offset, type, imm);
3752238SN/A        microOps[1] = new MicroStrQTFpXRegUop(machInst, dest, base,
37611851Sbrandon.potter@amd.com                                              offset, type, imm);
3772238SN/A    }
3782238SN/A
3791354SN/A    microOps[0]->setDelayedCommit();
3801354SN/A    microOps[1]->setLastMicroop();
38110796Sbrandon.potter@amd.com}
38210796Sbrandon.potter@amd.com
3831354SN/ABigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst,
3841354SN/A                             OpClass __opClass, IntRegIndex dest,
3851354SN/A                             int64_t imm) :
3861354SN/A    PredMacroOp(mnem, machInst, __opClass)
3871354SN/A{
3881354SN/A    numMicroops = 2;
3891354SN/A    microOps = new StaticInstPtr[numMicroops];
3901354SN/A
3911354SN/A    microOps[0] = new MicroLdrQBFpXLitUop(machInst, dest, imm);
3921354SN/A    microOps[1] = new MicroLdrQTFpXLitUop(machInst, dest, imm);
39310796Sbrandon.potter@amd.com
3941354SN/A    microOps[0]->setDelayedCommit();
39510796Sbrandon.potter@amd.com    microOps[1]->setLastMicroop();
3961354SN/A}
3971354SN/A
3981354SN/AVldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
3991354SN/A                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
40010796Sbrandon.potter@amd.com                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
40110796Sbrandon.potter@amd.com    PredMacroOp(mnem, machInst, __opClass)
40210796Sbrandon.potter@amd.com{
40310796Sbrandon.potter@amd.com    assert(regs > 0 && regs <= 4);
40410796Sbrandon.potter@amd.com    assert(regs % elems == 0);
40510796Sbrandon.potter@amd.com
40610796Sbrandon.potter@amd.com    numMicroops = (regs > 2) ? 2 : 1;
40710796Sbrandon.potter@amd.com    bool wb = (rm != 15);
40810796Sbrandon.potter@amd.com    bool deinterleave = (elems > 1);
40910796Sbrandon.potter@amd.com
41010796Sbrandon.potter@amd.com    if (wb) numMicroops++;
411360SN/A    if (deinterleave) numMicroops += (regs / elems);
412360SN/A    microOps = new StaticInstPtr[numMicroops];
413360SN/A
414360SN/A    RegIndex rMid = deinterleave ? NumFloatV7ArchRegs : vd * 2;
415360SN/A
416360SN/A    uint32_t noAlign = TLB::MustBeOne;
417360SN/A
41811759Sbrandon.potter@amd.com    unsigned uopIdx = 0;
4193113Sgblack@eecs.umich.edu    switch (regs) {
4203113Sgblack@eecs.umich.edu      case 4:
4213113Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4223113Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4233113Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4243113Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
4253113Sgblack@eecs.umich.edu        break;
4263113Sgblack@eecs.umich.edu      case 3:
4273113Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4283113Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4293113Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
4303113Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
4313113Sgblack@eecs.umich.edu        break;
4323113Sgblack@eecs.umich.edu      case 2:
4333113Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4343113Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4354189Sgblack@eecs.umich.edu        break;
4364189Sgblack@eecs.umich.edu      case 1:
4373113Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
4383113Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4393113Sgblack@eecs.umich.edu        break;
4403113Sgblack@eecs.umich.edu      default:
4418737Skoansin.tan@gmail.com        // Unknown number of registers
4423113Sgblack@eecs.umich.edu        microOps[uopIdx++] = new Unknown(machInst);
4438737Skoansin.tan@gmail.com    }
4443277Sgblack@eecs.umich.edu    if (wb) {
4455515SMichael.Adler@intel.com        if (rm != 15 && rm != 13) {
4465515SMichael.Adler@intel.com            microOps[uopIdx++] =
4475515SMichael.Adler@intel.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
4485515SMichael.Adler@intel.com        } else {
4495515SMichael.Adler@intel.com            microOps[uopIdx++] =
4508737Skoansin.tan@gmail.com                new MicroAddiUop(machInst, rn, rn, regs * 8);
4513277Sgblack@eecs.umich.edu        }
4528737Skoansin.tan@gmail.com    }
4533277Sgblack@eecs.umich.edu    if (deinterleave) {
4548737Skoansin.tan@gmail.com        switch (elems) {
4553277Sgblack@eecs.umich.edu          case 4:
4568737Skoansin.tan@gmail.com            assert(regs == 4);
4573113Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>(
4583113Sgblack@eecs.umich.edu                    size, machInst, vd * 2, rMid, inc * 2);
4593113Sgblack@eecs.umich.edu            break;
4603113Sgblack@eecs.umich.edu          case 3:
4618737Skoansin.tan@gmail.com            assert(regs == 3);
4623113Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>(
4638737Skoansin.tan@gmail.com                    size, machInst, vd * 2, rMid, inc * 2);
4643114Sgblack@eecs.umich.edu            break;
4658737Skoansin.tan@gmail.com          case 2:
4663114Sgblack@eecs.umich.edu            assert(regs == 4 || regs == 2);
4678737Skoansin.tan@gmail.com            if (regs == 4) {
4683114Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4698737Skoansin.tan@gmail.com                        size, machInst, vd * 2, rMid, inc * 2);
47011906SBrandon.Potter@amd.com                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4714061Sgblack@eecs.umich.edu                        size, machInst, vd * 2 + 2, rMid + 4, inc * 2);
4724061Sgblack@eecs.umich.edu            } else {
4738737Skoansin.tan@gmail.com                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4743113Sgblack@eecs.umich.edu                        size, machInst, vd * 2, rMid, inc * 2);
4758737Skoansin.tan@gmail.com            }
4763113Sgblack@eecs.umich.edu            break;
4773113Sgblack@eecs.umich.edu          default:
4783113Sgblack@eecs.umich.edu            // Bad number of elements to deinterleave
4793113Sgblack@eecs.umich.edu            microOps[uopIdx++] = new Unknown(machInst);
4803113Sgblack@eecs.umich.edu        }
4813113Sgblack@eecs.umich.edu    }
4823113Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
4833113Sgblack@eecs.umich.edu
4844189Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
4854189Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
4863113Sgblack@eecs.umich.edu        assert(uopPtr);
4873113Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
4883113Sgblack@eecs.umich.edu    }
4898737Skoansin.tan@gmail.com    microOps[numMicroops - 1]->setLastMicroop();
4903113Sgblack@eecs.umich.edu}
4918737Skoansin.tan@gmail.com
4923113Sgblack@eecs.umich.eduVldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
4938737Skoansin.tan@gmail.com                         OpClass __opClass, bool all, unsigned elems,
4943113Sgblack@eecs.umich.edu                         RegIndex rn, RegIndex vd, unsigned regs,
4953113Sgblack@eecs.umich.edu                         unsigned inc, uint32_t size, uint32_t align,
4963113Sgblack@eecs.umich.edu                         RegIndex rm, unsigned lane) :
4973113Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
4983113Sgblack@eecs.umich.edu{
4993113Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
5003113Sgblack@eecs.umich.edu    assert(regs % elems == 0);
50111906SBrandon.Potter@amd.com
5023113Sgblack@eecs.umich.edu    unsigned eBytes = (1 << size);
5033113Sgblack@eecs.umich.edu    unsigned loadSize = eBytes * elems;
5048852Sandreas.hansson@arm.com    unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) /
50511906SBrandon.Potter@amd.com                        sizeof(FloatRegBits);
5063113Sgblack@eecs.umich.edu
5073113Sgblack@eecs.umich.edu    assert(loadRegs > 0 && loadRegs <= 4);
5083113Sgblack@eecs.umich.edu
5093113Sgblack@eecs.umich.edu    numMicroops = 1;
5103113Sgblack@eecs.umich.edu    bool wb = (rm != 15);
5113113Sgblack@eecs.umich.edu
5123113Sgblack@eecs.umich.edu    if (wb) numMicroops++;
5133113Sgblack@eecs.umich.edu    numMicroops += (regs / elems);
5143113Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
5158852Sandreas.hansson@arm.com
51611906SBrandon.Potter@amd.com    RegIndex ufp0 = NumFloatV7ArchRegs;
5173113Sgblack@eecs.umich.edu
5183113Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
5193113Sgblack@eecs.umich.edu    switch (loadSize) {
5206686Stjones1@inf.ed.ac.uk      case 1:
5213113Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>(
5223113Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5233113Sgblack@eecs.umich.edu        break;
52411759Sbrandon.potter@amd.com      case 2:
52511759Sbrandon.potter@amd.com        if (eBytes == 2) {
52611759Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>(
52711759Sbrandon.potter@amd.com                    machInst, ufp0, rn, 0, align);
52811759Sbrandon.potter@amd.com        } else {
52911759Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>(
53011759Sbrandon.potter@amd.com                    machInst, ufp0, rn, 0, align);
53111812Sbaz21@cam.ac.uk        }
53211812Sbaz21@cam.ac.uk        break;
53311812Sbaz21@cam.ac.uk      case 3:
53411759Sbrandon.potter@amd.com        microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>(
53511812Sbaz21@cam.ac.uk                machInst, ufp0, rn, 0, align);
53611759Sbrandon.potter@amd.com        break;
53711759Sbrandon.potter@amd.com      case 4:
53811759Sbrandon.potter@amd.com        switch (eBytes) {
53911759Sbrandon.potter@amd.com          case 1:
54011759Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>(
54111759Sbrandon.potter@amd.com                    machInst, ufp0, rn, 0, align);
54211759Sbrandon.potter@amd.com            break;
54311812Sbaz21@cam.ac.uk          case 2:
54411812Sbaz21@cam.ac.uk            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>(
54511812Sbaz21@cam.ac.uk                    machInst, ufp0, rn, 0, align);
54611812Sbaz21@cam.ac.uk            break;
54711812Sbaz21@cam.ac.uk          case 4:
54811812Sbaz21@cam.ac.uk            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>(
54911812Sbaz21@cam.ac.uk                    machInst, ufp0, rn, 0, align);
55011759Sbrandon.potter@amd.com            break;
55111759Sbrandon.potter@amd.com        }
55211812Sbaz21@cam.ac.uk        break;
55311812Sbaz21@cam.ac.uk      case 6:
55411759Sbrandon.potter@amd.com        microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>(
55511812Sbaz21@cam.ac.uk                machInst, ufp0, rn, 0, align);
55611812Sbaz21@cam.ac.uk        break;
55711812Sbaz21@cam.ac.uk      case 8:
55811812Sbaz21@cam.ac.uk        switch (eBytes) {
55911812Sbaz21@cam.ac.uk          case 2:
56011812Sbaz21@cam.ac.uk            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>(
56111812Sbaz21@cam.ac.uk                    machInst, ufp0, rn, 0, align);
56211759Sbrandon.potter@amd.com            break;
56311759Sbrandon.potter@amd.com          case 4:
56411759Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>(
56511759Sbrandon.potter@amd.com                    machInst, ufp0, rn, 0, align);
566378SN/A            break;
567378SN/A        }
5689141Smarc.orr@gmail.com        break;
5699141Smarc.orr@gmail.com      case 12:
570360SN/A        microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>(
5711450SN/A                machInst, ufp0, rn, 0, align);
57211856Sbrandon.potter@amd.com        break;
573360SN/A      case 16:
5746701Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>(
57511856Sbrandon.potter@amd.com                machInst, ufp0, rn, 0, align);
57611856Sbrandon.potter@amd.com        break;
577360SN/A      default:
57810930Sbrandon.potter@amd.com        // Unrecognized load size
579360SN/A        microOps[uopIdx++] = new Unknown(machInst);
58011856Sbrandon.potter@amd.com    }
58111856Sbrandon.potter@amd.com    if (wb) {
58210496Ssteve.reinhardt@amd.com        if (rm != 15 && rm != 13) {
58311856Sbrandon.potter@amd.com            microOps[uopIdx++] =
58411856Sbrandon.potter@amd.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
5851458SN/A        } else {
586360SN/A            microOps[uopIdx++] =
58711856Sbrandon.potter@amd.com                new MicroAddiUop(machInst, rn, rn, loadSize);
58811856Sbrandon.potter@amd.com        }
58911856Sbrandon.potter@amd.com    }
59011856Sbrandon.potter@amd.com    switch (elems) {
59111856Sbrandon.potter@amd.com      case 4:
59211856Sbrandon.potter@amd.com        assert(regs == 4);
59311856Sbrandon.potter@amd.com        switch (size) {
59411856Sbrandon.potter@amd.com          case 0:
59510496Ssteve.reinhardt@amd.com            if (all) {
59611856Sbrandon.potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>(
59711856Sbrandon.potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
59811856Sbrandon.potter@amd.com            } else {
59911856Sbrandon.potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>(
60011856Sbrandon.potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
60110930Sbrandon.potter@amd.com            }
6029141Smarc.orr@gmail.com            break;
603360SN/A          case 1:
604360SN/A            if (all) {
605360SN/A                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>(
60611907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
60711907SBrandon.Potter@amd.com            } else {
60811907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>(
609360SN/A                        machInst, vd * 2, ufp0, inc * 2, lane);
61011907SBrandon.Potter@amd.com            }
61111907SBrandon.Potter@amd.com            break;
61211907SBrandon.Potter@amd.com          case 2:
61311907SBrandon.Potter@amd.com            if (all) {
61411907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>(
61511907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
61611907SBrandon.Potter@amd.com            } else {
61711907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>(
61811907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
61911907SBrandon.Potter@amd.com            }
62011907SBrandon.Potter@amd.com            break;
62111907SBrandon.Potter@amd.com          default:
62211907SBrandon.Potter@amd.com            // Bad size
62311907SBrandon.Potter@amd.com            microOps[uopIdx++] = new Unknown(machInst);
624360SN/A            break;
62511907SBrandon.Potter@amd.com        }
6261458SN/A        break;
627360SN/A      case 3:
62811907SBrandon.Potter@amd.com        assert(regs == 3);
62911907SBrandon.Potter@amd.com        switch (size) {
63011907SBrandon.Potter@amd.com          case 0:
63111907SBrandon.Potter@amd.com            if (all) {
63211907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>(
63311907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
63411907SBrandon.Potter@amd.com            } else {
63511907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>(
63611907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
63711907SBrandon.Potter@amd.com            }
638360SN/A            break;
63911907SBrandon.Potter@amd.com          case 1:
64011907SBrandon.Potter@amd.com            if (all) {
64111907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>(
642360SN/A                        machInst, vd * 2, ufp0, inc * 2);
643360SN/A            } else {
64411907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>(
64511907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
64611907SBrandon.Potter@amd.com            }
64711907SBrandon.Potter@amd.com            break;
648360SN/A          case 2:
64911907SBrandon.Potter@amd.com            if (all) {
650360SN/A                microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>(
651360SN/A                        machInst, vd * 2, ufp0, inc * 2);
65211907SBrandon.Potter@amd.com            } else {
6533669Sbinkertn@umich.edu                microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>(
65411907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
65511907SBrandon.Potter@amd.com            }
65611907SBrandon.Potter@amd.com            break;
65711907SBrandon.Potter@amd.com          default:
65811907SBrandon.Potter@amd.com            // Bad size
65911907SBrandon.Potter@amd.com            microOps[uopIdx++] = new Unknown(machInst);
66011907SBrandon.Potter@amd.com            break;
66111907SBrandon.Potter@amd.com        }
66211907SBrandon.Potter@amd.com        break;
66311907SBrandon.Potter@amd.com      case 2:
66411907SBrandon.Potter@amd.com        assert(regs == 2);
66511907SBrandon.Potter@amd.com        assert(loadRegs <= 2);
66611907SBrandon.Potter@amd.com        switch (size) {
66711907SBrandon.Potter@amd.com          case 0:
66811907SBrandon.Potter@amd.com            if (all) {
66911907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>(
67011907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
67111907SBrandon.Potter@amd.com            } else {
67211907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>(
67311907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
67411907SBrandon.Potter@amd.com            }
6751706SN/A            break;
67611907SBrandon.Potter@amd.com          case 1:
67711907SBrandon.Potter@amd.com            if (all) {
67811907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>(
67911907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
68011907SBrandon.Potter@amd.com            } else {
68111907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>(
68210496Ssteve.reinhardt@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
68310496Ssteve.reinhardt@amd.com            }
68411907SBrandon.Potter@amd.com            break;
68511907SBrandon.Potter@amd.com          case 2:
68611907SBrandon.Potter@amd.com            if (all) {
68711907SBrandon.Potter@amd.com                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>(
68811907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2);
68911907SBrandon.Potter@amd.com            } else {
69010496Ssteve.reinhardt@amd.com                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>(
69111907SBrandon.Potter@amd.com                        machInst, vd * 2, ufp0, inc * 2, lane);
69211907SBrandon.Potter@amd.com            }
69311907SBrandon.Potter@amd.com            break;
69411907SBrandon.Potter@amd.com          default:
69510496Ssteve.reinhardt@amd.com            // Bad size
69610496Ssteve.reinhardt@amd.com            microOps[uopIdx++] = new Unknown(machInst);
69711907SBrandon.Potter@amd.com            break;
69811907SBrandon.Potter@amd.com        }
69911907SBrandon.Potter@amd.com        break;
70011907SBrandon.Potter@amd.com      case 1:
70111907SBrandon.Potter@amd.com        assert(regs == 1 || (all && regs == 2));
70211907SBrandon.Potter@amd.com        assert(loadRegs <= 2);
70311907SBrandon.Potter@amd.com        for (unsigned offset = 0; offset < regs; offset++) {
70411907SBrandon.Potter@amd.com            switch (size) {
70511907SBrandon.Potter@amd.com              case 0:
70611907SBrandon.Potter@amd.com                if (all) {
70711907SBrandon.Potter@amd.com                    microOps[uopIdx++] =
70811907SBrandon.Potter@amd.com                        new MicroUnpackAllNeon2to2Uop<uint8_t>(
70911907SBrandon.Potter@amd.com                            machInst, (vd + offset) * 2, ufp0, inc * 2);
71011907SBrandon.Potter@amd.com                } else {
71111907SBrandon.Potter@amd.com                    microOps[uopIdx++] =
71211907SBrandon.Potter@amd.com                        new MicroUnpackNeon2to2Uop<uint8_t>(
71311907SBrandon.Potter@amd.com                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
71411907SBrandon.Potter@amd.com                }
71511907SBrandon.Potter@amd.com                break;
71611907SBrandon.Potter@amd.com              case 1:
71711907SBrandon.Potter@amd.com                if (all) {
71811907SBrandon.Potter@amd.com                    microOps[uopIdx++] =
71911907SBrandon.Potter@amd.com                        new MicroUnpackAllNeon2to2Uop<uint16_t>(
72011907SBrandon.Potter@amd.com                            machInst, (vd + offset) * 2, ufp0, inc * 2);
72111907SBrandon.Potter@amd.com                } else {
722360SN/A                    microOps[uopIdx++] =
72311907SBrandon.Potter@amd.com                        new MicroUnpackNeon2to2Uop<uint16_t>(
72411907SBrandon.Potter@amd.com                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
72511907SBrandon.Potter@amd.com                }
72611907SBrandon.Potter@amd.com                break;
72711907SBrandon.Potter@amd.com              case 2:
72811907SBrandon.Potter@amd.com                if (all) {
72911907SBrandon.Potter@amd.com                    microOps[uopIdx++] =
73011907SBrandon.Potter@amd.com                        new MicroUnpackAllNeon2to2Uop<uint32_t>(
73111907SBrandon.Potter@amd.com                            machInst, (vd + offset) * 2, ufp0, inc * 2);
73211907SBrandon.Potter@amd.com                } else {
73311907SBrandon.Potter@amd.com                    microOps[uopIdx++] =
73411907SBrandon.Potter@amd.com                        new MicroUnpackNeon2to2Uop<uint32_t>(
73511907SBrandon.Potter@amd.com                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
736360SN/A                }
737360SN/A                break;
73810027SChris.Adeniyi-Jones@arm.com              default:
73910027SChris.Adeniyi-Jones@arm.com                // Bad size
74010027SChris.Adeniyi-Jones@arm.com                microOps[uopIdx++] = new Unknown(machInst);
74111851Sbrandon.potter@amd.com                break;
74210027SChris.Adeniyi-Jones@arm.com            }
74310027SChris.Adeniyi-Jones@arm.com        }
74411907SBrandon.Potter@amd.com        break;
74510027SChris.Adeniyi-Jones@arm.com      default:
74610027SChris.Adeniyi-Jones@arm.com        // Bad number of elements to unpack
74710027SChris.Adeniyi-Jones@arm.com        microOps[uopIdx++] = new Unknown(machInst);
74810027SChris.Adeniyi-Jones@arm.com    }
74910027SChris.Adeniyi-Jones@arm.com    assert(uopIdx == numMicroops);
75011851Sbrandon.potter@amd.com
75111851Sbrandon.potter@amd.com    for (unsigned i = 0; i < numMicroops - 1; i++) {
75210027SChris.Adeniyi-Jones@arm.com        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
75311907SBrandon.Potter@amd.com        assert(uopPtr);
75410027SChris.Adeniyi-Jones@arm.com        uopPtr->setDelayedCommit();
75510027SChris.Adeniyi-Jones@arm.com    }
75610633Smichaelupton@gmail.com    microOps[numMicroops - 1]->setLastMicroop();
75710633Smichaelupton@gmail.com}
75810633Smichaelupton@gmail.com
75911851Sbrandon.potter@amd.comVstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
76010633Smichaelupton@gmail.com                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
76110633Smichaelupton@gmail.com                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
76210633Smichaelupton@gmail.com    PredMacroOp(mnem, machInst, __opClass)
76310633Smichaelupton@gmail.com{
76410633Smichaelupton@gmail.com    assert(regs > 0 && regs <= 4);
76510633Smichaelupton@gmail.com    assert(regs % elems == 0);
76610633Smichaelupton@gmail.com
76710633Smichaelupton@gmail.com    numMicroops = (regs > 2) ? 2 : 1;
76810633Smichaelupton@gmail.com    bool wb = (rm != 15);
76910633Smichaelupton@gmail.com    bool interleave = (elems > 1);
77010203SAli.Saidi@ARM.com
77110203SAli.Saidi@ARM.com    if (wb) numMicroops++;
77210203SAli.Saidi@ARM.com    if (interleave) numMicroops += (regs / elems);
77311851Sbrandon.potter@amd.com    microOps = new StaticInstPtr[numMicroops];
77411851Sbrandon.potter@amd.com
77510203SAli.Saidi@ARM.com    uint32_t noAlign = TLB::MustBeOne;
77610203SAli.Saidi@ARM.com
77710203SAli.Saidi@ARM.com    RegIndex rMid = interleave ? NumFloatV7ArchRegs : vd * 2;
77810203SAli.Saidi@ARM.com
77910203SAli.Saidi@ARM.com    unsigned uopIdx = 0;
78010203SAli.Saidi@ARM.com    if (interleave) {
78110203SAli.Saidi@ARM.com        switch (elems) {
78210203SAli.Saidi@ARM.com          case 4:
78310203SAli.Saidi@ARM.com            assert(regs == 4);
78410203SAli.Saidi@ARM.com            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>(
78510203SAli.Saidi@ARM.com                    size, machInst, rMid, vd * 2, inc * 2);
78611851Sbrandon.potter@amd.com            break;
78711851Sbrandon.potter@amd.com          case 3:
78810203SAli.Saidi@ARM.com            assert(regs == 3);
78910203SAli.Saidi@ARM.com            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>(
79010203SAli.Saidi@ARM.com                    size, machInst, rMid, vd * 2, inc * 2);
79110203SAli.Saidi@ARM.com            break;
79210203SAli.Saidi@ARM.com          case 2:
79310203SAli.Saidi@ARM.com            assert(regs == 4 || regs == 2);
79410203SAli.Saidi@ARM.com            if (regs == 4) {
79510203SAli.Saidi@ARM.com                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
79610850SGiacomo.Gabrielli@arm.com                        size, machInst, rMid, vd * 2, inc * 2);
79710850SGiacomo.Gabrielli@arm.com                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
79810850SGiacomo.Gabrielli@arm.com                        size, machInst, rMid + 4, vd * 2 + 2, inc * 2);
79911851Sbrandon.potter@amd.com            } else {
80010850SGiacomo.Gabrielli@arm.com                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
80110850SGiacomo.Gabrielli@arm.com                        size, machInst, rMid, vd * 2, inc * 2);
80210850SGiacomo.Gabrielli@arm.com            }
80310850SGiacomo.Gabrielli@arm.com            break;
80410850SGiacomo.Gabrielli@arm.com          default:
80510850SGiacomo.Gabrielli@arm.com            // Bad number of elements to interleave
80610850SGiacomo.Gabrielli@arm.com            microOps[uopIdx++] = new Unknown(machInst);
80710850SGiacomo.Gabrielli@arm.com        }
80810850SGiacomo.Gabrielli@arm.com    }
80910850SGiacomo.Gabrielli@arm.com    switch (regs) {
81010850SGiacomo.Gabrielli@arm.com      case 4:
81110850SGiacomo.Gabrielli@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
81210850SGiacomo.Gabrielli@arm.com                size, machInst, rMid, rn, 0, align);
81310850SGiacomo.Gabrielli@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
81410850SGiacomo.Gabrielli@arm.com                size, machInst, rMid + 4, rn, 16, noAlign);
81510850SGiacomo.Gabrielli@arm.com        break;
81610850SGiacomo.Gabrielli@arm.com      case 3:
81710850SGiacomo.Gabrielli@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
81810850SGiacomo.Gabrielli@arm.com                size, machInst, rMid, rn, 0, align);
81910850SGiacomo.Gabrielli@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
82010850SGiacomo.Gabrielli@arm.com                size, machInst, rMid + 4, rn, 16, noAlign);
82110850SGiacomo.Gabrielli@arm.com        break;
82210850SGiacomo.Gabrielli@arm.com      case 2:
82310850SGiacomo.Gabrielli@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
82410850SGiacomo.Gabrielli@arm.com                size, machInst, rMid, rn, 0, align);
82510850SGiacomo.Gabrielli@arm.com        break;
82610850SGiacomo.Gabrielli@arm.com      case 1:
82710850SGiacomo.Gabrielli@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
82810850SGiacomo.Gabrielli@arm.com                size, machInst, rMid, rn, 0, align);
82910850SGiacomo.Gabrielli@arm.com        break;
83010850SGiacomo.Gabrielli@arm.com      default:
83110850SGiacomo.Gabrielli@arm.com        // Unknown number of registers
8326640Svince@csl.cornell.edu        microOps[uopIdx++] = new Unknown(machInst);
8336640Svince@csl.cornell.edu    }
8346640Svince@csl.cornell.edu    if (wb) {
83511851Sbrandon.potter@amd.com        if (rm != 15 && rm != 13) {
83611851Sbrandon.potter@amd.com            microOps[uopIdx++] =
8376640Svince@csl.cornell.edu                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
8386640Svince@csl.cornell.edu        } else {
8396701Sgblack@eecs.umich.edu            microOps[uopIdx++] =
8406701Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, regs * 8);
84110793Sbrandon.potter@amd.com        }
8426640Svince@csl.cornell.edu    }
84311758Sbrandon.potter@amd.com    assert(uopIdx == numMicroops);
84411758Sbrandon.potter@amd.com
84511758Sbrandon.potter@amd.com    for (unsigned i = 0; i < numMicroops - 1; i++) {
8466640Svince@csl.cornell.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
8478706Sandreas.hansson@arm.com        assert(uopPtr);
8486640Svince@csl.cornell.edu        uopPtr->setDelayedCommit();
8496701Sgblack@eecs.umich.edu    }
8506640Svince@csl.cornell.edu    microOps[numMicroops - 1]->setLastMicroop();
851360SN/A}
8521999SN/A
8531999SN/AVstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
8541999SN/A                         OpClass __opClass, bool all, unsigned elems,
85511851Sbrandon.potter@amd.com                         RegIndex rn, RegIndex vd, unsigned regs,
8562680Sktlim@umich.edu                         unsigned inc, uint32_t size, uint32_t align,
8571999SN/A                         RegIndex rm, unsigned lane) :
8581999SN/A    PredMacroOp(mnem, machInst, __opClass)
8591999SN/A{
8606701Sgblack@eecs.umich.edu    assert(!all);
8618852Sandreas.hansson@arm.com    assert(regs > 0 && regs <= 4);
8626701Sgblack@eecs.umich.edu    assert(regs % elems == 0);
8631999SN/A
8646701Sgblack@eecs.umich.edu    unsigned eBytes = (1 << size);
8651999SN/A    unsigned storeSize = eBytes * elems;
8666701Sgblack@eecs.umich.edu    unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) /
8671999SN/A                         sizeof(FloatRegBits);
8681999SN/A
8691999SN/A    assert(storeRegs > 0 && storeRegs <= 4);
8701999SN/A
8711999SN/A    numMicroops = 1;
8723669Sbinkertn@umich.edu    bool wb = (rm != 15);
8733669Sbinkertn@umich.edu
8743669Sbinkertn@umich.edu    if (wb) numMicroops++;
8751999SN/A    numMicroops += (regs / elems);
8761999SN/A    microOps = new StaticInstPtr[numMicroops];
8771999SN/A
8782218SN/A    RegIndex ufp0 = NumFloatV7ArchRegs;
8791999SN/A
8801999SN/A    unsigned uopIdx = 0;
8811999SN/A    switch (elems) {
8821999SN/A      case 4:
8831999SN/A        assert(regs == 4);
8841999SN/A        switch (size) {
8851999SN/A          case 0:
8861999SN/A            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>(
88711856Sbrandon.potter@amd.com                    machInst, ufp0, vd * 2, inc * 2, lane);
8881999SN/A            break;
8896701Sgblack@eecs.umich.edu          case 1:
89011856Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>(
89111856Sbrandon.potter@amd.com                    machInst, ufp0, vd * 2, inc * 2, lane);
89210931Sbrandon.potter@amd.com            break;
89311856Sbrandon.potter@amd.com          case 2:
89411856Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>(
8951999SN/A                    machInst, ufp0, vd * 2, inc * 2, lane);
89611856Sbrandon.potter@amd.com            break;
8971999SN/A          default:
89811856Sbrandon.potter@amd.com            // Bad size
8991999SN/A            microOps[uopIdx++] = new Unknown(machInst);
90011856Sbrandon.potter@amd.com            break;
9011999SN/A        }
90211856Sbrandon.potter@amd.com        break;
9031999SN/A      case 3:
9041999SN/A        assert(regs == 3);
9055877Shsul@eecs.umich.edu        switch (size) {
9065877Shsul@eecs.umich.edu          case 0:
9075877Shsul@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>(
90811851Sbrandon.potter@amd.com                    machInst, ufp0, vd * 2, inc * 2, lane);
9095877Shsul@eecs.umich.edu            break;
9106701Sgblack@eecs.umich.edu          case 1:
9116701Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>(
9126701Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9136701Sgblack@eecs.umich.edu            break;
9146701Sgblack@eecs.umich.edu          case 2:
91510027SChris.Adeniyi-Jones@arm.com            microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>(
91610027SChris.Adeniyi-Jones@arm.com                    machInst, ufp0, vd * 2, inc * 2, lane);
91710027SChris.Adeniyi-Jones@arm.com            break;
91810027SChris.Adeniyi-Jones@arm.com          default:
91910027SChris.Adeniyi-Jones@arm.com            // Bad size
9205877Shsul@eecs.umich.edu            microOps[uopIdx++] = new Unknown(machInst);
92110318Sandreas.hansson@arm.com            break;
92210318Sandreas.hansson@arm.com        }
9235877Shsul@eecs.umich.edu        break;
9245877Shsul@eecs.umich.edu      case 2:
9255877Shsul@eecs.umich.edu        assert(regs == 2);
9265877Shsul@eecs.umich.edu        assert(storeRegs <= 2);
92710486Stjablin@gmail.com        switch (size) {
92810486Stjablin@gmail.com          case 0:
9295877Shsul@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>(
93011905SBrandon.Potter@amd.com                    machInst, ufp0, vd * 2, inc * 2, lane);
93111905SBrandon.Potter@amd.com            break;
93211905SBrandon.Potter@amd.com          case 1:
93311905SBrandon.Potter@amd.com            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>(
93410027SChris.Adeniyi-Jones@arm.com                    machInst, ufp0, vd * 2, inc * 2, lane);
9355877Shsul@eecs.umich.edu            break;
93611905SBrandon.Potter@amd.com          case 2:
93711905SBrandon.Potter@amd.com            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>(
9385877Shsul@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9395877Shsul@eecs.umich.edu            break;
94010027SChris.Adeniyi-Jones@arm.com          default:
9415877Shsul@eecs.umich.edu            // Bad size
9425877Shsul@eecs.umich.edu            microOps[uopIdx++] = new Unknown(machInst);
9435877Shsul@eecs.umich.edu            break;
94410027SChris.Adeniyi-Jones@arm.com        }
94511905SBrandon.Potter@amd.com        break;
94610027SChris.Adeniyi-Jones@arm.com      case 1:
94710027SChris.Adeniyi-Jones@arm.com        assert(regs == 1 || (all && regs == 2));
94810027SChris.Adeniyi-Jones@arm.com        assert(storeRegs <= 2);
94910027SChris.Adeniyi-Jones@arm.com        for (unsigned offset = 0; offset < regs; offset++) {
9505877Shsul@eecs.umich.edu            switch (size) {
95110027SChris.Adeniyi-Jones@arm.com              case 0:
95210027SChris.Adeniyi-Jones@arm.com                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>(
95310027SChris.Adeniyi-Jones@arm.com                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
95410027SChris.Adeniyi-Jones@arm.com                break;
95511905SBrandon.Potter@amd.com              case 1:
95610027SChris.Adeniyi-Jones@arm.com                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>(
95711905SBrandon.Potter@amd.com                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
95810027SChris.Adeniyi-Jones@arm.com                break;
95910027SChris.Adeniyi-Jones@arm.com              case 2:
96010027SChris.Adeniyi-Jones@arm.com                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>(
96110027SChris.Adeniyi-Jones@arm.com                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
96210027SChris.Adeniyi-Jones@arm.com                break;
96310027SChris.Adeniyi-Jones@arm.com              default:
9645877Shsul@eecs.umich.edu                // Bad size
9655877Shsul@eecs.umich.edu                microOps[uopIdx++] = new Unknown(machInst);
9665877Shsul@eecs.umich.edu                break;
96710027SChris.Adeniyi-Jones@arm.com            }
96810027SChris.Adeniyi-Jones@arm.com        }
9698601Ssteve.reinhardt@amd.com        break;
97010027SChris.Adeniyi-Jones@arm.com      default:
9715877Shsul@eecs.umich.edu        // Bad number of elements to unpack
9725877Shsul@eecs.umich.edu        microOps[uopIdx++] = new Unknown(machInst);
9731999SN/A    }
974378SN/A    switch (storeSize) {
975360SN/A      case 1:
9761450SN/A        microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>(
97711851Sbrandon.potter@amd.com                machInst, ufp0, rn, 0, align);
9782680Sktlim@umich.edu        break;
979360SN/A      case 2:
980360SN/A        if (eBytes == 2) {
981360SN/A            microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>(
9826701Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9838852Sandreas.hansson@arm.com        } else {
9846701Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>(
9856701Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9866701Sgblack@eecs.umich.edu        }
9876701Sgblack@eecs.umich.edu        break;
988360SN/A      case 3:
9893669Sbinkertn@umich.edu        microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>(
9903669Sbinkertn@umich.edu                machInst, ufp0, rn, 0, align);
9913669Sbinkertn@umich.edu        break;
992360SN/A      case 4:
993360SN/A        switch (eBytes) {
994360SN/A          case 1:
995360SN/A            microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>(
9962218SN/A                    machInst, ufp0, rn, 0, align);
997360SN/A            break;
9988706Sandreas.hansson@arm.com          case 2:
999360SN/A            microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>(
10001458SN/A                    machInst, ufp0, rn, 0, align);
1001360SN/A            break;
1002360SN/A          case 4:
1003360SN/A            microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>(
10045074Ssaidi@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10055074Ssaidi@eecs.umich.edu            break;
10065074Ssaidi@eecs.umich.edu        }
100711851Sbrandon.potter@amd.com        break;
10085074Ssaidi@eecs.umich.edu      case 6:
10095074Ssaidi@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>(
10105074Ssaidi@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10115074Ssaidi@eecs.umich.edu        break;
10126701Sgblack@eecs.umich.edu      case 8:
10138852Sandreas.hansson@arm.com        switch (eBytes) {
10146701Sgblack@eecs.umich.edu          case 2:
10155074Ssaidi@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>(
10166701Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10175074Ssaidi@eecs.umich.edu            break;
10185074Ssaidi@eecs.umich.edu          case 4:
10195074Ssaidi@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>(
10205074Ssaidi@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10215208Ssaidi@eecs.umich.edu            break;
10225208Ssaidi@eecs.umich.edu        }
10235208Ssaidi@eecs.umich.edu        break;
10245208Ssaidi@eecs.umich.edu      case 12:
10255074Ssaidi@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>(
10265074Ssaidi@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10275208Ssaidi@eecs.umich.edu        break;
10285074Ssaidi@eecs.umich.edu      case 16:
10295074Ssaidi@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>(
10305074Ssaidi@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10315074Ssaidi@eecs.umich.edu        break;
10328706Sandreas.hansson@arm.com      default:
10335074Ssaidi@eecs.umich.edu        // Bad store size
10345074Ssaidi@eecs.umich.edu        microOps[uopIdx++] = new Unknown(machInst);
10355074Ssaidi@eecs.umich.edu    }
10365074Ssaidi@eecs.umich.edu    if (wb) {
10375074Ssaidi@eecs.umich.edu        if (rm != 15 && rm != 13) {
103810027SChris.Adeniyi-Jones@arm.com            microOps[uopIdx++] =
103910027SChris.Adeniyi-Jones@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
104010027SChris.Adeniyi-Jones@arm.com        } else {
104111851Sbrandon.potter@amd.com            microOps[uopIdx++] =
104210027SChris.Adeniyi-Jones@arm.com                new MicroAddiUop(machInst, rn, rn, storeSize);
104310027SChris.Adeniyi-Jones@arm.com        }
104410027SChris.Adeniyi-Jones@arm.com    }
104510027SChris.Adeniyi-Jones@arm.com    assert(uopIdx == numMicroops);
104610027SChris.Adeniyi-Jones@arm.com
104710793Sbrandon.potter@amd.com    for (unsigned i = 0; i < numMicroops - 1; i++) {
104810027SChris.Adeniyi-Jones@arm.com        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
104910027SChris.Adeniyi-Jones@arm.com        assert(uopPtr);
105010027SChris.Adeniyi-Jones@arm.com        uopPtr->setDelayedCommit();
105110027SChris.Adeniyi-Jones@arm.com    }
105210027SChris.Adeniyi-Jones@arm.com    microOps[numMicroops - 1]->setLastMicroop();
105310027SChris.Adeniyi-Jones@arm.com}
105410027SChris.Adeniyi-Jones@arm.com
105510027SChris.Adeniyi-Jones@arm.comVldMultOp64::VldMultOp64(const char *mnem, ExtMachInst machInst,
105610027SChris.Adeniyi-Jones@arm.com                         OpClass __opClass, RegIndex rn, RegIndex vd,
105710027SChris.Adeniyi-Jones@arm.com                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
105810027SChris.Adeniyi-Jones@arm.com                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
105910027SChris.Adeniyi-Jones@arm.com    PredMacroOp(mnem, machInst, __opClass)
106010027SChris.Adeniyi-Jones@arm.com{
106110027SChris.Adeniyi-Jones@arm.com    RegIndex vx = NumFloatV8ArchRegs / 4;
106210027SChris.Adeniyi-Jones@arm.com    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
106310027SChris.Adeniyi-Jones@arm.com    bool baseIsSP = isSP((IntRegIndex) rnsp);
106410027SChris.Adeniyi-Jones@arm.com
106510027SChris.Adeniyi-Jones@arm.com    numMicroops = wb ? 1 : 0;
106610027SChris.Adeniyi-Jones@arm.com
106710027SChris.Adeniyi-Jones@arm.com    int totNumBytes = numRegs * dataSize / 8;
106810027SChris.Adeniyi-Jones@arm.com    assert(totNumBytes <= 64);
106910027SChris.Adeniyi-Jones@arm.com
107010027SChris.Adeniyi-Jones@arm.com    // The guiding principle here is that no more than 16 bytes can be
107110027SChris.Adeniyi-Jones@arm.com    // transferred at a time
107210027SChris.Adeniyi-Jones@arm.com    int numMemMicroops = totNumBytes / 16;
107310027SChris.Adeniyi-Jones@arm.com    int residuum = totNumBytes % 16;
107410027SChris.Adeniyi-Jones@arm.com    if (residuum)
10751999SN/A        ++numMemMicroops;
10761999SN/A    numMicroops += numMemMicroops;
10771999SN/A
107811856Sbrandon.potter@amd.com    int numMarshalMicroops = numRegs / 2 + (numRegs % 2 ? 1 : 0);
10791999SN/A    numMicroops += numMarshalMicroops;
10806701Sgblack@eecs.umich.edu
108111856Sbrandon.potter@amd.com    microOps = new StaticInstPtr[numMicroops];
108211856Sbrandon.potter@amd.com    unsigned uopIdx = 0;
108310931Sbrandon.potter@amd.com    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
108411856Sbrandon.potter@amd.com        TLB::AllowUnaligned;
108511856Sbrandon.potter@amd.com
10861999SN/A    int i = 0;
108711856Sbrandon.potter@amd.com    for(; i < numMemMicroops - 1; ++i) {
10881999SN/A        microOps[uopIdx++] = new MicroNeonLoad64(
10892764Sstever@eecs.umich.edu            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
10902064SN/A            baseIsSP, 16 /* accSize */, eSize);
109110931Sbrandon.potter@amd.com    }
10922064SN/A    microOps[uopIdx++] =  new MicroNeonLoad64(
10932064SN/A        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
109410931Sbrandon.potter@amd.com        residuum ? residuum : 16 /* accSize */, eSize);
10952064SN/A
10961999SN/A    // Writeback microop: the post-increment amount is encoded in "Rm": a
10971999SN/A    // 64-bit general register OR as '11111' for an immediate value equal to
10982218SN/A    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
10991999SN/A    if (wb) {
110010931Sbrandon.potter@amd.com        if (rm != ((RegIndex) INTREG_X31)) {
11011999SN/A            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
11021999SN/A                                                      UXTX, 0);
11031999SN/A        } else {
11041999SN/A            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
11051999SN/A                                                   totNumBytes);
1106378SN/A        }
1107360SN/A    }
11081450SN/A
110911851Sbrandon.potter@amd.com    for (int i = 0; i < numMarshalMicroops; ++i) {
11102680Sktlim@umich.edu        microOps[uopIdx++] = new MicroDeintNeon64(
1111360SN/A            machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
1112360SN/A            numStructElems, numRegs, i /* step */);
1113360SN/A    }
11146701Sgblack@eecs.umich.edu
11158852Sandreas.hansson@arm.com    assert(uopIdx == numMicroops);
11166701Sgblack@eecs.umich.edu
11176701Sgblack@eecs.umich.edu    for (int i = 0; i < numMicroops - 1; ++i) {
11186701Sgblack@eecs.umich.edu        microOps[i]->setDelayedCommit();
11196701Sgblack@eecs.umich.edu    }
1120360SN/A    microOps[numMicroops - 1]->setLastMicroop();
11213669Sbinkertn@umich.edu}
11223669Sbinkertn@umich.edu
11233669Sbinkertn@umich.eduVstMultOp64::VstMultOp64(const char *mnem, ExtMachInst machInst,
1124360SN/A                         OpClass __opClass, RegIndex rn, RegIndex vd,
1125360SN/A                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
1126360SN/A                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
1127360SN/A    PredMacroOp(mnem, machInst, __opClass)
11281458SN/A{
1129360SN/A    RegIndex vx = NumFloatV8ArchRegs / 4;
11308706Sandreas.hansson@arm.com    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
1131360SN/A    bool baseIsSP = isSP((IntRegIndex) rnsp);
11321458SN/A
1133360SN/A    numMicroops = wb ? 1 : 0;
1134360SN/A
11351999SN/A    int totNumBytes = numRegs * dataSize / 8;
11361999SN/A    assert(totNumBytes <= 64);
11371999SN/A
113811851Sbrandon.potter@amd.com    // The guiding principle here is that no more than 16 bytes can be
11392680Sktlim@umich.edu    // transferred at a time
11401999SN/A    int numMemMicroops = totNumBytes / 16;
11411999SN/A    int residuum = totNumBytes % 16;
11421999SN/A    if (residuum)
11436701Sgblack@eecs.umich.edu        ++numMemMicroops;
11448852Sandreas.hansson@arm.com    numMicroops += numMemMicroops;
11456701Sgblack@eecs.umich.edu
11466701Sgblack@eecs.umich.edu    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
11476701Sgblack@eecs.umich.edu    numMicroops += numMarshalMicroops;
11486701Sgblack@eecs.umich.edu
11491999SN/A    microOps = new StaticInstPtr[numMicroops];
11503669Sbinkertn@umich.edu    unsigned uopIdx = 0;
11513669Sbinkertn@umich.edu
11523669Sbinkertn@umich.edu    for(int i = 0; i < numMarshalMicroops; ++i) {
11532764Sstever@eecs.umich.edu        microOps[uopIdx++] = new MicroIntNeon64(
11542064SN/A            machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
11552064SN/A            numStructElems, numRegs, i /* step */);
11562064SN/A    }
11571999SN/A
11581999SN/A    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
11592064SN/A        TLB::AllowUnaligned;
11601999SN/A
11611999SN/A    int i = 0;
11621999SN/A    for(; i < numMemMicroops - 1; ++i) {
11631999SN/A        microOps[uopIdx++] = new MicroNeonStore64(
11648706Sandreas.hansson@arm.com            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
11651999SN/A            baseIsSP, 16 /* accSize */, eSize);
11661999SN/A    }
11671999SN/A    microOps[uopIdx++] = new MicroNeonStore64(
11681999SN/A        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
1169378SN/A        residuum ? residuum : 16 /* accSize */, eSize);
1170360SN/A
11711450SN/A    // Writeback microop: the post-increment amount is encoded in "Rm": a
117211856Sbrandon.potter@amd.com    // 64-bit general register OR as '11111' for an immediate value equal to
1173360SN/A    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
11746701Sgblack@eecs.umich.edu    if (wb) {
117511856Sbrandon.potter@amd.com        if (rm != ((RegIndex) INTREG_X31)) {
117611856Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
1177360SN/A                                                      UXTX, 0);
117811380Salexandru.dutu@amd.com        } else {
1179360SN/A            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
118011856Sbrandon.potter@amd.com                                                   totNumBytes);
118111856Sbrandon.potter@amd.com        }
11821458SN/A    }
118311856Sbrandon.potter@amd.com
1184360SN/A    assert(uopIdx == numMicroops);
1185360SN/A
118610931Sbrandon.potter@amd.com    for (int i = 0; i < numMicroops - 1; i++) {
1187360SN/A        microOps[i]->setDelayedCommit();
1188360SN/A    }
11891458SN/A    microOps[numMicroops - 1]->setLastMicroop();
1190360SN/A}
119110931Sbrandon.potter@amd.com
11922021SN/AVldSingleOp64::VldSingleOp64(const char *mnem, ExtMachInst machInst,
11931458SN/A                             OpClass __opClass, RegIndex rn, RegIndex vd,
1194360SN/A                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
1195360SN/A                             uint8_t numStructElems, uint8_t index, bool wb,
1196360SN/A                             bool replicate) :
11971706SN/A    PredMacroOp(mnem, machInst, __opClass)
11981706SN/A{
11991706SN/A    RegIndex vx = NumFloatV8ArchRegs / 4;
120011851Sbrandon.potter@amd.com    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
12012680Sktlim@umich.edu    bool baseIsSP = isSP((IntRegIndex) rnsp);
12021706SN/A
120311799Sbrandon.potter@amd.com    numMicroops = wb ? 1 : 0;
120411799Sbrandon.potter@amd.com
120511799Sbrandon.potter@amd.com    int eSizeBytes = 1 << eSize;
12061706SN/A    int totNumBytes = numStructElems * eSizeBytes;
12071706SN/A    assert(totNumBytes <= 64);
12086701Sgblack@eecs.umich.edu
12098852Sandreas.hansson@arm.com    // The guiding principle here is that no more than 16 bytes can be
12106701Sgblack@eecs.umich.edu    // transferred at a time
12116701Sgblack@eecs.umich.edu    int numMemMicroops = totNumBytes / 16;
12126701Sgblack@eecs.umich.edu    int residuum = totNumBytes % 16;
12136701Sgblack@eecs.umich.edu    if (residuum)
12141706SN/A        ++numMemMicroops;
12153669Sbinkertn@umich.edu    numMicroops += numMemMicroops;
12163669Sbinkertn@umich.edu
12173669Sbinkertn@umich.edu    int numMarshalMicroops = numStructElems / 2 + (numStructElems % 2 ? 1 : 0);
12181706SN/A    numMicroops += numMarshalMicroops;
12191706SN/A
12201706SN/A    microOps = new StaticInstPtr[numMicroops];
12211706SN/A    unsigned uopIdx = 0;
12222218SN/A
12231706SN/A    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
122411759Sbrandon.potter@amd.com        TLB::AllowUnaligned;
122511799Sbrandon.potter@amd.com
12261706SN/A    int i = 0;
12271706SN/A    for (; i < numMemMicroops - 1; ++i) {
12281706SN/A        microOps[uopIdx++] = new MicroNeonLoad64(
122911886Sbrandon.potter@amd.com            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
123011886Sbrandon.potter@amd.com            baseIsSP, 16 /* accSize */, eSize);
123111886Sbrandon.potter@amd.com    }
123211886Sbrandon.potter@amd.com    microOps[uopIdx++] = new MicroNeonLoad64(
123311886Sbrandon.potter@amd.com        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
123411886Sbrandon.potter@amd.com        residuum ? residuum : 16 /* accSize */, eSize);
123511886Sbrandon.potter@amd.com
123611886Sbrandon.potter@amd.com    // Writeback microop: the post-increment amount is encoded in "Rm": a
123711886Sbrandon.potter@amd.com    // 64-bit general register OR as '11111' for an immediate value equal to
123811886Sbrandon.potter@amd.com    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
123911886Sbrandon.potter@amd.com    if (wb) {
124011886Sbrandon.potter@amd.com        if (rm != ((RegIndex) INTREG_X31)) {
124111886Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
124211886Sbrandon.potter@amd.com                                                      UXTX, 0);
124311886Sbrandon.potter@amd.com        } else {
124411886Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
124511886Sbrandon.potter@amd.com                                                   totNumBytes);
124611886Sbrandon.potter@amd.com        }
124711886Sbrandon.potter@amd.com    }
124811886Sbrandon.potter@amd.com
124911886Sbrandon.potter@amd.com    for(int i = 0; i < numMarshalMicroops; ++i) {
125011886Sbrandon.potter@amd.com        microOps[uopIdx++] = new MicroUnpackNeon64(
125111886Sbrandon.potter@amd.com            machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
125211886Sbrandon.potter@amd.com            numStructElems, index, i /* step */, replicate);
125311886Sbrandon.potter@amd.com    }
125411886Sbrandon.potter@amd.com
125511886Sbrandon.potter@amd.com    assert(uopIdx == numMicroops);
125611886Sbrandon.potter@amd.com
125711886Sbrandon.potter@amd.com    for (int i = 0; i < numMicroops - 1; i++) {
125811886Sbrandon.potter@amd.com        microOps[i]->setDelayedCommit();
125911886Sbrandon.potter@amd.com    }
126011886Sbrandon.potter@amd.com    microOps[numMicroops - 1]->setLastMicroop();
126111886Sbrandon.potter@amd.com}
126211886Sbrandon.potter@amd.com
126311886Sbrandon.potter@amd.comVstSingleOp64::VstSingleOp64(const char *mnem, ExtMachInst machInst,
126411886Sbrandon.potter@amd.com                             OpClass __opClass, RegIndex rn, RegIndex vd,
126511886Sbrandon.potter@amd.com                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
126611886Sbrandon.potter@amd.com                             uint8_t numStructElems, uint8_t index, bool wb,
126711886Sbrandon.potter@amd.com                             bool replicate) :
126811886Sbrandon.potter@amd.com    PredMacroOp(mnem, machInst, __opClass)
126911886Sbrandon.potter@amd.com{
127011886Sbrandon.potter@amd.com    RegIndex vx = NumFloatV8ArchRegs / 4;
127111886Sbrandon.potter@amd.com    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
127211886Sbrandon.potter@amd.com    bool baseIsSP = isSP((IntRegIndex) rnsp);
127311886Sbrandon.potter@amd.com
127411886Sbrandon.potter@amd.com    numMicroops = wb ? 1 : 0;
127511886Sbrandon.potter@amd.com
127611886Sbrandon.potter@amd.com    int eSizeBytes = 1 << eSize;
127711886Sbrandon.potter@amd.com    int totNumBytes = numStructElems * eSizeBytes;
127811886Sbrandon.potter@amd.com    assert(totNumBytes <= 64);
127911886Sbrandon.potter@amd.com
128011886Sbrandon.potter@amd.com    // The guiding principle here is that no more than 16 bytes can be
128111886Sbrandon.potter@amd.com    // transferred at a time
128211886Sbrandon.potter@amd.com    int numMemMicroops = totNumBytes / 16;
128311886Sbrandon.potter@amd.com    int residuum = totNumBytes % 16;
128411886Sbrandon.potter@amd.com    if (residuum)
128511886Sbrandon.potter@amd.com        ++numMemMicroops;
128611886Sbrandon.potter@amd.com    numMicroops += numMemMicroops;
128711886Sbrandon.potter@amd.com
128811886Sbrandon.potter@amd.com    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
128911886Sbrandon.potter@amd.com    numMicroops += numMarshalMicroops;
129011886Sbrandon.potter@amd.com
129111886Sbrandon.potter@amd.com    microOps = new StaticInstPtr[numMicroops];
129211886Sbrandon.potter@amd.com    unsigned uopIdx = 0;
129311886Sbrandon.potter@amd.com
129411886Sbrandon.potter@amd.com    for(int i = 0; i < numMarshalMicroops; ++i) {
129511886Sbrandon.potter@amd.com        microOps[uopIdx++] = new MicroPackNeon64(
129611886Sbrandon.potter@amd.com            machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
129711886Sbrandon.potter@amd.com            numStructElems, index, i /* step */, replicate);
129811886Sbrandon.potter@amd.com    }
129911886Sbrandon.potter@amd.com
130011911SBrandon.Potter@amd.com    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
130111911SBrandon.Potter@amd.com        TLB::AllowUnaligned;
130211911SBrandon.Potter@amd.com
130311911SBrandon.Potter@amd.com    int i = 0;
130411911SBrandon.Potter@amd.com    for(; i < numMemMicroops - 1; ++i) {
130511911SBrandon.Potter@amd.com        microOps[uopIdx++] = new MicroNeonStore64(
130611911SBrandon.Potter@amd.com            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
130711886Sbrandon.potter@amd.com            baseIsSP, 16 /* accsize */, eSize);
130811886Sbrandon.potter@amd.com    }
130911886Sbrandon.potter@amd.com    microOps[uopIdx++] = new MicroNeonStore64(
131011886Sbrandon.potter@amd.com        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
131111886Sbrandon.potter@amd.com        residuum ? residuum : 16 /* accSize */, eSize);
131211886Sbrandon.potter@amd.com
131311886Sbrandon.potter@amd.com    // Writeback microop: the post-increment amount is encoded in "Rm": a
131411886Sbrandon.potter@amd.com    // 64-bit general register OR as '11111' for an immediate value equal to
131511886Sbrandon.potter@amd.com    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
131611886Sbrandon.potter@amd.com    if (wb) {
131711886Sbrandon.potter@amd.com        if (rm != ((RegIndex) INTREG_X31)) {
131811886Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
131911886Sbrandon.potter@amd.com                                                      UXTX, 0);
132011886Sbrandon.potter@amd.com        } else {
132111886Sbrandon.potter@amd.com            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
132211886Sbrandon.potter@amd.com                                                   totNumBytes);
132311886Sbrandon.potter@amd.com        }
132411886Sbrandon.potter@amd.com    }
132511886Sbrandon.potter@amd.com
132611886Sbrandon.potter@amd.com    assert(uopIdx == numMicroops);
132711886Sbrandon.potter@amd.com
132811886Sbrandon.potter@amd.com    for (int i = 0; i < numMicroops - 1; i++) {
132911886Sbrandon.potter@amd.com        microOps[i]->setDelayedCommit();
133011886Sbrandon.potter@amd.com    }
133111886Sbrandon.potter@amd.com    microOps[numMicroops - 1]->setLastMicroop();
133211886Sbrandon.potter@amd.com}
133311886Sbrandon.potter@amd.com
133411886Sbrandon.potter@amd.comMacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
133511886Sbrandon.potter@amd.com                             OpClass __opClass, IntRegIndex rn,
133611886Sbrandon.potter@amd.com                             RegIndex vd, bool single, bool up,
133711886Sbrandon.potter@amd.com                             bool writeback, bool load, uint32_t offset) :
133811886Sbrandon.potter@amd.com    PredMacroOp(mnem, machInst, __opClass)
133911886Sbrandon.potter@amd.com{
134011886Sbrandon.potter@amd.com    int i = 0;
134111886Sbrandon.potter@amd.com
134211886Sbrandon.potter@amd.com    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
134311886Sbrandon.potter@amd.com    // to be functionally identical except that fldmx is deprecated. For now
134411886Sbrandon.potter@amd.com    // we'll assume they're otherwise interchangable.
134511886Sbrandon.potter@amd.com    int count = (single ? offset : (offset / 2));
134611886Sbrandon.potter@amd.com    if (count == 0 || count > NumFloatV7ArchRegs)
134711886Sbrandon.potter@amd.com        warn_once("Bad offset field for VFP load/store multiple.\n");
134811886Sbrandon.potter@amd.com    if (count == 0) {
134911886Sbrandon.potter@amd.com        // Force there to be at least one microop so the macroop makes sense.
135011886Sbrandon.potter@amd.com        writeback = true;
135111886Sbrandon.potter@amd.com    }
135211886Sbrandon.potter@amd.com    if (count > NumFloatV7ArchRegs)
135311886Sbrandon.potter@amd.com        count = NumFloatV7ArchRegs;
135411886Sbrandon.potter@amd.com
135511886Sbrandon.potter@amd.com    numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
135611886Sbrandon.potter@amd.com    microOps = new StaticInstPtr[numMicroops];
135711886Sbrandon.potter@amd.com
135811886Sbrandon.potter@amd.com    int64_t addr = 0;
135911886Sbrandon.potter@amd.com
136011886Sbrandon.potter@amd.com    if (!up)
13611706SN/A        addr = 4 * offset;
13621706SN/A
13631706SN/A    bool tempUp = up;
13641706SN/A    for (int j = 0; j < count; j++) {
136511856Sbrandon.potter@amd.com        if (load) {
13661706SN/A            if (single) {
13676701Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
136811856Sbrandon.potter@amd.com                                                  tempUp, addr);
136911856Sbrandon.potter@amd.com            } else {
13701706SN/A                microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn,
137111856Sbrandon.potter@amd.com                                                    tempUp, addr);
137211856Sbrandon.potter@amd.com                microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp,
13731706SN/A                                                    addr + (up ? 4 : -4));
137411856Sbrandon.potter@amd.com            }
13751706SN/A        } else {
13761706SN/A            if (single) {
137710931Sbrandon.potter@amd.com                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
13781706SN/A                                                  tempUp, addr);
13791706SN/A            } else {
13802218SN/A                microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn,
13811706SN/A                                                    tempUp, addr);
138211759Sbrandon.potter@amd.com                microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp,
13831706SN/A                                                    addr + (up ? 4 : -4));
13841706SN/A            }
13851706SN/A        }
13861706SN/A        if (!tempUp) {
13871706SN/A            addr -= (single ? 4 : 8);
13881999SN/A            // The microops don't handle negative displacement, so turn if we
13891999SN/A            // hit zero, flip polarity and start adding.
13901999SN/A            if (addr <= 0) {
139111856Sbrandon.potter@amd.com                tempUp = true;
13921999SN/A                addr = -addr;
13936701Sgblack@eecs.umich.edu            }
139411856Sbrandon.potter@amd.com        } else {
139510931Sbrandon.potter@amd.com            addr += (single ? 4 : 8);
139611856Sbrandon.potter@amd.com        }
139711856Sbrandon.potter@amd.com    }
13981999SN/A
139911856Sbrandon.potter@amd.com    if (writeback) {
14001999SN/A        if (up) {
140111856Sbrandon.potter@amd.com            microOps[i++] =
140211856Sbrandon.potter@amd.com                new MicroAddiUop(machInst, rn, rn, 4 * offset);
140311856Sbrandon.potter@amd.com        } else {
14041999SN/A            microOps[i++] =
14056227Snate@binkert.org                new MicroSubiUop(machInst, rn, rn, 4 * offset);
14061999SN/A        }
14072461SN/A    }
140811856Sbrandon.potter@amd.com
140911856Sbrandon.potter@amd.com    assert(numMicroops == i);
14108737Skoansin.tan@gmail.com    microOps[numMicroops - 1]->setLastMicroop();
14111999SN/A
141211856Sbrandon.potter@amd.com    for (StaticInstPtr *curUop = microOps;
141311856Sbrandon.potter@amd.com            !(*curUop)->isLastMicroop(); curUop++) {
14141999SN/A        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
14151999SN/A        assert(uopPtr);
141610931Sbrandon.potter@amd.com        uopPtr->setDelayedCommit();
14171999SN/A    }
14186227Snate@binkert.org}
14191999SN/A
14201999SN/Astd::string
14211999SN/AMicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14222218SN/A{
14231999SN/A    std::stringstream ss;
142410629Sjthestness@gmail.com    printMnemonic(ss);
14251999SN/A    printReg(ss, ura);
14261999SN/A    ss << ", ";
142711385Sbrandon.potter@amd.com    printReg(ss, urb);
1428360SN/A    ss << ", ";
14291450SN/A    ccprintf(ss, "#%d", imm);
143011851Sbrandon.potter@amd.com    return ss.str();
143111385Sbrandon.potter@amd.com}
1432360SN/A
14336701Sgblack@eecs.umich.edustd::string
14346701Sgblack@eecs.umich.eduMicroIntImmXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14356701Sgblack@eecs.umich.edu{
143611383Sbrandon.potter@amd.com    std::stringstream ss;
143711383Sbrandon.potter@amd.com    printMnemonic(ss);
14388324Ssteve.reinhardt@amd.com    printReg(ss, ura);
143910486Stjablin@gmail.com    ss << ", ";
1440360SN/A    printReg(ss, urb);
144111385Sbrandon.potter@amd.com    ss << ", ";
144211385Sbrandon.potter@amd.com    ccprintf(ss, "#%d", imm);
14439008Sgblack@eecs.umich.edu    return ss.str();
144411383Sbrandon.potter@amd.com}
144511383Sbrandon.potter@amd.com
144611383Sbrandon.potter@amd.comstd::string
144711383Sbrandon.potter@amd.comMicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
144811383Sbrandon.potter@amd.com{
144911383Sbrandon.potter@amd.com    std::stringstream ss;
145011383Sbrandon.potter@amd.com    printMnemonic(ss);
145111383Sbrandon.potter@amd.com    ss << "[PC,CPSR]";
145211383Sbrandon.potter@amd.com    return ss.str();
14538324Ssteve.reinhardt@amd.com}
145411383Sbrandon.potter@amd.com
145511383Sbrandon.potter@amd.comstd::string
145611383Sbrandon.potter@amd.comMicroIntRegXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
145711383Sbrandon.potter@amd.com{
145811383Sbrandon.potter@amd.com    std::stringstream ss;
145911383Sbrandon.potter@amd.com    printMnemonic(ss);
146011383Sbrandon.potter@amd.com    printReg(ss, ura);
146111383Sbrandon.potter@amd.com    ccprintf(ss, ", ");
146211383Sbrandon.potter@amd.com    printReg(ss, urb);
146311383Sbrandon.potter@amd.com    printExtendOperand(false, ss, (IntRegIndex)urc, type, shiftAmt);
146411383Sbrandon.potter@amd.com    return ss.str();
146511383Sbrandon.potter@amd.com}
146611383Sbrandon.potter@amd.com
146711383Sbrandon.potter@amd.comstd::string
146811383Sbrandon.potter@amd.comMicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
146911383Sbrandon.potter@amd.com{
147011383Sbrandon.potter@amd.com    std::stringstream ss;
147111383Sbrandon.potter@amd.com    printMnemonic(ss);
147211383Sbrandon.potter@amd.com    printReg(ss, ura);
147311383Sbrandon.potter@amd.com    ss << ", ";
147411383Sbrandon.potter@amd.com    printReg(ss, urb);
147511383Sbrandon.potter@amd.com    return ss.str();
147611383Sbrandon.potter@amd.com}
147711383Sbrandon.potter@amd.com
14788324Ssteve.reinhardt@amd.comstd::string
14795877Shsul@eecs.umich.eduMicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
148010486Stjablin@gmail.com{
148110486Stjablin@gmail.com    std::stringstream ss;
148211383Sbrandon.potter@amd.com    printMnemonic(ss);
148311383Sbrandon.potter@amd.com    printReg(ss, ura);
148411383Sbrandon.potter@amd.com    ss << ", ";
148511856Sbrandon.potter@amd.com    printReg(ss, urb);
148611624Smichael.lebeane@amd.com    ss << ", ";
148711856Sbrandon.potter@amd.com    printReg(ss, urc);
148811856Sbrandon.potter@amd.com    return ss.str();
148911856Sbrandon.potter@amd.com}
149011856Sbrandon.potter@amd.com
149111624Smichael.lebeane@amd.comstd::string
149211624Smichael.lebeane@amd.comMicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
149311624Smichael.lebeane@amd.com{
149411856Sbrandon.potter@amd.com    std::stringstream ss;
149511856Sbrandon.potter@amd.com    printMnemonic(ss);
149611383Sbrandon.potter@amd.com    if (isFloating())
149711856Sbrandon.potter@amd.com        printReg(ss, ura + FP_Reg_Base);
1498360SN/A    else
149911913SBrandon.Potter@amd.com        printReg(ss, ura);
150011383Sbrandon.potter@amd.com    ss << ", [";
15018600Ssteve.reinhardt@amd.com    printReg(ss, urb);
150211383Sbrandon.potter@amd.com    ss << ", ";
150311383Sbrandon.potter@amd.com    ccprintf(ss, "#%d", imm);
150411383Sbrandon.potter@amd.com    ss << "]";
15058600Ssteve.reinhardt@amd.com    return ss.str();
15062544SN/A}
15072544SN/A
150811383Sbrandon.potter@amd.com}
150911383Sbrandon.potter@amd.com