macromem.cc revision 10037
17170Sgblack@eecs.umich.edu/*
210037SARM gem5 Developers * Copyright (c) 2010-2013 ARM Limited
37170Sgblack@eecs.umich.edu * All rights reserved
47170Sgblack@eecs.umich.edu *
57170Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
67170Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
77170Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
87170Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
97170Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
107170Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
117170Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
127170Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
137170Sgblack@eecs.umich.edu *
147170Sgblack@eecs.umich.edu * Copyright (c) 2007-2008 The Florida State University
157170Sgblack@eecs.umich.edu * All rights reserved.
167170Sgblack@eecs.umich.edu *
177170Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
187170Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
197170Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
207170Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
217170Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
227170Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
237170Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
247170Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
257170Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
267170Sgblack@eecs.umich.edu * this software without specific prior written permission.
277170Sgblack@eecs.umich.edu *
287170Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
297170Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
307170Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
317170Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
327170Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
337170Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
347170Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
357170Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
367170Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
377170Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
387170Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
397170Sgblack@eecs.umich.edu *
407170Sgblack@eecs.umich.edu * Authors: Stephen Hines
417170Sgblack@eecs.umich.edu */
427170Sgblack@eecs.umich.edu
438229Snate@binkert.org#include <sstream>
448229Snate@binkert.org
457170Sgblack@eecs.umich.edu#include "arch/arm/insts/macromem.hh"
4610037SARM gem5 Developers
478961Sgblack@eecs.umich.edu#include "arch/arm/generated/decoder.hh"
4810037SARM gem5 Developers#include "arch/arm/insts/neon64_mem.hh"
497170Sgblack@eecs.umich.edu
507853SMatt.Horsnell@ARM.comusing namespace std;
517170Sgblack@eecs.umich.eduusing namespace ArmISAInst;
527170Sgblack@eecs.umich.edu
537170Sgblack@eecs.umich.edunamespace ArmISA
547170Sgblack@eecs.umich.edu{
557170Sgblack@eecs.umich.edu
567170Sgblack@eecs.umich.eduMacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
577170Sgblack@eecs.umich.edu                       OpClass __opClass, IntRegIndex rn,
587170Sgblack@eecs.umich.edu                       bool index, bool up, bool user, bool writeback,
597170Sgblack@eecs.umich.edu                       bool load, uint32_t reglist) :
607170Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
617170Sgblack@eecs.umich.edu{
627170Sgblack@eecs.umich.edu    uint32_t regs = reglist;
637170Sgblack@eecs.umich.edu    uint32_t ones = number_of_ones(reglist);
648148SAli.Saidi@ARM.com    // Remember that writeback adds a uop or two and the temp register adds one
658148SAli.Saidi@ARM.com    numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1;
668148SAli.Saidi@ARM.com
678148SAli.Saidi@ARM.com    // It's technically legal to do a lot of nothing
688148SAli.Saidi@ARM.com    if (!ones)
698148SAli.Saidi@ARM.com        numMicroops = 1;
708148SAli.Saidi@ARM.com
717170Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
727170Sgblack@eecs.umich.edu    uint32_t addr = 0;
737170Sgblack@eecs.umich.edu
747170Sgblack@eecs.umich.edu    if (!up)
757170Sgblack@eecs.umich.edu        addr = (ones << 2) - 4;
767170Sgblack@eecs.umich.edu
777170Sgblack@eecs.umich.edu    if (!index)
787170Sgblack@eecs.umich.edu        addr += 4;
797170Sgblack@eecs.umich.edu
807190Sgblack@eecs.umich.edu    StaticInstPtr *uop = microOps;
817190Sgblack@eecs.umich.edu
827170Sgblack@eecs.umich.edu    // Add 0 to Rn and stick it in ureg0.
837170Sgblack@eecs.umich.edu    // This is equivalent to a move.
847190Sgblack@eecs.umich.edu    *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
857190Sgblack@eecs.umich.edu
867170Sgblack@eecs.umich.edu    unsigned reg = 0;
878148SAli.Saidi@ARM.com    unsigned regIdx = 0;
887170Sgblack@eecs.umich.edu    bool force_user = user & !bits(reglist, 15);
897170Sgblack@eecs.umich.edu    bool exception_ret = user & bits(reglist, 15);
907170Sgblack@eecs.umich.edu
917190Sgblack@eecs.umich.edu    for (int i = 0; i < ones; i++) {
927170Sgblack@eecs.umich.edu        // Find the next register.
937170Sgblack@eecs.umich.edu        while (!bits(regs, reg))
947170Sgblack@eecs.umich.edu            reg++;
957170Sgblack@eecs.umich.edu        replaceBits(regs, reg, 0);
967170Sgblack@eecs.umich.edu
978148SAli.Saidi@ARM.com        regIdx = reg;
987170Sgblack@eecs.umich.edu        if (force_user) {
997310Sgblack@eecs.umich.edu            regIdx = intRegInMode(MODE_USER, regIdx);
1007170Sgblack@eecs.umich.edu        }
1017170Sgblack@eecs.umich.edu
1027170Sgblack@eecs.umich.edu        if (load) {
1038148SAli.Saidi@ARM.com            if (writeback && i == ones - 1) {
1048148SAli.Saidi@ARM.com                // If it's a writeback and this is the last register
1058148SAli.Saidi@ARM.com                // do the load into a temporary register which we'll move
1068148SAli.Saidi@ARM.com                // into the final one later
1078148SAli.Saidi@ARM.com                *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0,
1088148SAli.Saidi@ARM.com                        up, addr);
1097170Sgblack@eecs.umich.edu            } else {
1108148SAli.Saidi@ARM.com                // Otherwise just do it normally
1118148SAli.Saidi@ARM.com                if (reg == INTREG_PC && exception_ret) {
1128148SAli.Saidi@ARM.com                    // This must be the exception return form of ldm.
1138148SAli.Saidi@ARM.com                    *++uop = new MicroLdrRetUop(machInst, regIdx,
1148148SAli.Saidi@ARM.com                                               INTREG_UREG0, up, addr);
1159640Snathanael.premillieu@irisa.fr                    if (!(condCode == COND_AL || condCode == COND_UC))
1169640Snathanael.premillieu@irisa.fr                        (*uop)->setFlag(StaticInst::IsCondControl);
1179640Snathanael.premillieu@irisa.fr                    else
1189640Snathanael.premillieu@irisa.fr                        (*uop)->setFlag(StaticInst::IsUncondControl);
1198148SAli.Saidi@ARM.com                } else {
1208148SAli.Saidi@ARM.com                    *++uop = new MicroLdrUop(machInst, regIdx,
1218148SAli.Saidi@ARM.com                                            INTREG_UREG0, up, addr);
1229250SAli.Saidi@ARM.com                    if (reg == INTREG_PC) {
1239250SAli.Saidi@ARM.com                        (*uop)->setFlag(StaticInst::IsControl);
1249250SAli.Saidi@ARM.com                        if (!(condCode == COND_AL || condCode == COND_UC))
1259250SAli.Saidi@ARM.com                            (*uop)->setFlag(StaticInst::IsCondControl);
1269250SAli.Saidi@ARM.com                        else
1279250SAli.Saidi@ARM.com                            (*uop)->setFlag(StaticInst::IsUncondControl);
1289250SAli.Saidi@ARM.com                        (*uop)->setFlag(StaticInst::IsIndirectControl);
1299250SAli.Saidi@ARM.com                    }
1308148SAli.Saidi@ARM.com                }
1317170Sgblack@eecs.umich.edu            }
1327170Sgblack@eecs.umich.edu        } else {
1337190Sgblack@eecs.umich.edu            *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
1347170Sgblack@eecs.umich.edu        }
1357170Sgblack@eecs.umich.edu
1367170Sgblack@eecs.umich.edu        if (up)
1377170Sgblack@eecs.umich.edu            addr += 4;
1387170Sgblack@eecs.umich.edu        else
1397170Sgblack@eecs.umich.edu            addr -= 4;
1407170Sgblack@eecs.umich.edu    }
1417170Sgblack@eecs.umich.edu
1428148SAli.Saidi@ARM.com    if (writeback && ones) {
1438148SAli.Saidi@ARM.com        // put the register update after we're done all loading
1448148SAli.Saidi@ARM.com        if (up)
1458148SAli.Saidi@ARM.com            *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4);
1468148SAli.Saidi@ARM.com        else
1478148SAli.Saidi@ARM.com            *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4);
1488148SAli.Saidi@ARM.com
1498148SAli.Saidi@ARM.com        // If this was a load move the last temporary value into place
1508148SAli.Saidi@ARM.com        // this way we can't take an exception after we update the base
1518148SAli.Saidi@ARM.com        // register.
1528148SAli.Saidi@ARM.com        if (load && reg == INTREG_PC && exception_ret) {
1538148SAli.Saidi@ARM.com            *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
1549368Snathanael.premillieu@irisa.fr            if (!(condCode == COND_AL || condCode == COND_UC))
1559368Snathanael.premillieu@irisa.fr                (*uop)->setFlag(StaticInst::IsCondControl);
1569368Snathanael.premillieu@irisa.fr            else
1579368Snathanael.premillieu@irisa.fr                (*uop)->setFlag(StaticInst::IsUncondControl);
1588148SAli.Saidi@ARM.com        } else if (load) {
1598148SAli.Saidi@ARM.com            *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1);
1608148SAli.Saidi@ARM.com            if (reg == INTREG_PC) {
1618542Sgblack@eecs.umich.edu                (*uop)->setFlag(StaticInst::IsControl);
1628542Sgblack@eecs.umich.edu                (*uop)->setFlag(StaticInst::IsCondControl);
1638542Sgblack@eecs.umich.edu                (*uop)->setFlag(StaticInst::IsIndirectControl);
1648148SAli.Saidi@ARM.com                // This is created as a RAS POP
1658148SAli.Saidi@ARM.com                if (rn == INTREG_SP)
1668542Sgblack@eecs.umich.edu                    (*uop)->setFlag(StaticInst::IsReturn);
1678148SAli.Saidi@ARM.com
1688148SAli.Saidi@ARM.com            }
1698148SAli.Saidi@ARM.com        }
1707170Sgblack@eecs.umich.edu    }
1717190Sgblack@eecs.umich.edu
1727190Sgblack@eecs.umich.edu    (*uop)->setLastMicroop();
1737343Sgblack@eecs.umich.edu
1747343Sgblack@eecs.umich.edu    for (StaticInstPtr *curUop = microOps;
1757343Sgblack@eecs.umich.edu            !(*curUop)->isLastMicroop(); curUop++) {
1767343Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
1777343Sgblack@eecs.umich.edu        assert(uopPtr);
1787343Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
1797343Sgblack@eecs.umich.edu    }
1807170Sgblack@eecs.umich.edu}
1817170Sgblack@eecs.umich.edu
18210037SARM gem5 DevelopersPairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
18310037SARM gem5 Developers                     uint32_t size, bool fp, bool load, bool noAlloc,
18410037SARM gem5 Developers                     bool signExt, bool exclusive, bool acrel,
18510037SARM gem5 Developers                     int64_t imm, AddrMode mode,
18610037SARM gem5 Developers                     IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) :
18710037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
18810037SARM gem5 Developers{
18910037SARM gem5 Developers    bool writeback = (mode != AddrMd_Offset);
19010037SARM gem5 Developers    numMicroops = 1 + (size / 4) + (writeback ? 1 : 0);
19110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
19210037SARM gem5 Developers
19310037SARM gem5 Developers    StaticInstPtr *uop = microOps;
19410037SARM gem5 Developers
19510037SARM gem5 Developers    bool post = (mode == AddrMd_PostIndex);
19610037SARM gem5 Developers
19710037SARM gem5 Developers    rn = makeSP(rn);
19810037SARM gem5 Developers
19910037SARM gem5 Developers    *uop = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, post ? 0 : imm);
20010037SARM gem5 Developers
20110037SARM gem5 Developers    if (fp) {
20210037SARM gem5 Developers        if (size == 16) {
20310037SARM gem5 Developers            if (load) {
20410037SARM gem5 Developers                *++uop = new MicroLdrQBFpXImmUop(machInst, rt,
20510037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
20610037SARM gem5 Developers                *++uop = new MicroLdrQTFpXImmUop(machInst, rt,
20710037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
20810037SARM gem5 Developers                *++uop = new MicroLdrQBFpXImmUop(machInst, rt2,
20910037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
21010037SARM gem5 Developers                *++uop = new MicroLdrQTFpXImmUop(machInst, rt2,
21110037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
21210037SARM gem5 Developers            } else {
21310037SARM gem5 Developers                *++uop = new MicroStrQBFpXImmUop(machInst, rt,
21410037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21510037SARM gem5 Developers                *++uop = new MicroStrQTFpXImmUop(machInst, rt,
21610037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21710037SARM gem5 Developers                *++uop = new MicroStrQBFpXImmUop(machInst, rt2,
21810037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
21910037SARM gem5 Developers                *++uop = new MicroStrQTFpXImmUop(machInst, rt2,
22010037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22110037SARM gem5 Developers            }
22210037SARM gem5 Developers        } else if (size == 8) {
22310037SARM gem5 Developers            if (load) {
22410037SARM gem5 Developers                *++uop = new MicroLdrFpXImmUop(machInst, rt,
22510037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
22610037SARM gem5 Developers                *++uop = new MicroLdrFpXImmUop(machInst, rt2,
22710037SARM gem5 Developers                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
22810037SARM gem5 Developers            } else {
22910037SARM gem5 Developers                *++uop = new MicroStrFpXImmUop(machInst, rt,
23010037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
23110037SARM gem5 Developers                *++uop = new MicroStrFpXImmUop(machInst, rt2,
23210037SARM gem5 Developers                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
23310037SARM gem5 Developers            }
23410037SARM gem5 Developers        } else if (size == 4) {
23510037SARM gem5 Developers            if (load) {
23610037SARM gem5 Developers                *++uop = new MicroLdrDFpXImmUop(machInst, rt, rt2,
23710037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
23810037SARM gem5 Developers            } else {
23910037SARM gem5 Developers                *++uop = new MicroStrDFpXImmUop(machInst, rt, rt2,
24010037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
24110037SARM gem5 Developers            }
24210037SARM gem5 Developers        }
24310037SARM gem5 Developers    } else {
24410037SARM gem5 Developers        if (size == 8) {
24510037SARM gem5 Developers            if (load) {
24610037SARM gem5 Developers                *++uop = new MicroLdrXImmUop(machInst, rt, INTREG_UREG0,
24710037SARM gem5 Developers                        0, noAlloc, exclusive, acrel);
24810037SARM gem5 Developers                *++uop = new MicroLdrXImmUop(machInst, rt2, INTREG_UREG0,
24910037SARM gem5 Developers                        size, noAlloc, exclusive, acrel);
25010037SARM gem5 Developers            } else {
25110037SARM gem5 Developers                *++uop = new MicroStrXImmUop(machInst, rt, INTREG_UREG0,
25210037SARM gem5 Developers                        0, noAlloc, exclusive, acrel);
25310037SARM gem5 Developers                *++uop = new MicroStrXImmUop(machInst, rt2, INTREG_UREG0,
25410037SARM gem5 Developers                        size, noAlloc, exclusive, acrel);
25510037SARM gem5 Developers            }
25610037SARM gem5 Developers        } else if (size == 4) {
25710037SARM gem5 Developers            if (load) {
25810037SARM gem5 Developers                if (signExt) {
25910037SARM gem5 Developers                    *++uop = new MicroLdrDSXImmUop(machInst, rt, rt2,
26010037SARM gem5 Developers                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
26110037SARM gem5 Developers                } else {
26210037SARM gem5 Developers                    *++uop = new MicroLdrDUXImmUop(machInst, rt, rt2,
26310037SARM gem5 Developers                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
26410037SARM gem5 Developers                }
26510037SARM gem5 Developers            } else {
26610037SARM gem5 Developers                *++uop = new MicroStrDXImmUop(machInst, rt, rt2,
26710037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
26810037SARM gem5 Developers            }
26910037SARM gem5 Developers        }
27010037SARM gem5 Developers    }
27110037SARM gem5 Developers
27210037SARM gem5 Developers    if (writeback) {
27310037SARM gem5 Developers        *++uop = new MicroAddXiUop(machInst, rn, INTREG_UREG0,
27410037SARM gem5 Developers                                   post ? imm : 0);
27510037SARM gem5 Developers    }
27610037SARM gem5 Developers
27710037SARM gem5 Developers    (*uop)->setLastMicroop();
27810037SARM gem5 Developers
27910037SARM gem5 Developers    for (StaticInstPtr *curUop = microOps;
28010037SARM gem5 Developers            !(*curUop)->isLastMicroop(); curUop++) {
28110037SARM gem5 Developers        (*curUop)->setDelayedCommit();
28210037SARM gem5 Developers    }
28310037SARM gem5 Developers}
28410037SARM gem5 Developers
28510037SARM gem5 DevelopersBigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst,
28610037SARM gem5 Developers                             OpClass __opClass, bool load, IntRegIndex dest,
28710037SARM gem5 Developers                             IntRegIndex base, int64_t imm) :
28810037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
28910037SARM gem5 Developers{
29010037SARM gem5 Developers    numMicroops = 2;
29110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
29210037SARM gem5 Developers
29310037SARM gem5 Developers    if (load) {
29410037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
29510037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
29610037SARM gem5 Developers    } else {
29710037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
29810037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
29910037SARM gem5 Developers    }
30010037SARM gem5 Developers    microOps[0]->setDelayedCommit();
30110037SARM gem5 Developers    microOps[1]->setLastMicroop();
30210037SARM gem5 Developers}
30310037SARM gem5 Developers
30410037SARM gem5 DevelopersBigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst,
30510037SARM gem5 Developers                               OpClass __opClass, bool load, IntRegIndex dest,
30610037SARM gem5 Developers                               IntRegIndex base, int64_t imm) :
30710037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
30810037SARM gem5 Developers{
30910037SARM gem5 Developers    numMicroops = 3;
31010037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
31110037SARM gem5 Developers
31210037SARM gem5 Developers    if (load) {
31310037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, 0);
31410037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, 0);
31510037SARM gem5 Developers    } else {
31610037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, 0);
31710037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, 0);
31810037SARM gem5 Developers    }
31910037SARM gem5 Developers    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
32010037SARM gem5 Developers
32110037SARM gem5 Developers    microOps[0]->setDelayedCommit();
32210037SARM gem5 Developers    microOps[1]->setDelayedCommit();
32310037SARM gem5 Developers    microOps[2]->setLastMicroop();
32410037SARM gem5 Developers}
32510037SARM gem5 Developers
32610037SARM gem5 DevelopersBigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst,
32710037SARM gem5 Developers                             OpClass __opClass, bool load, IntRegIndex dest,
32810037SARM gem5 Developers                             IntRegIndex base, int64_t imm) :
32910037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
33010037SARM gem5 Developers{
33110037SARM gem5 Developers    numMicroops = 3;
33210037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
33310037SARM gem5 Developers
33410037SARM gem5 Developers    if (load) {
33510037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
33610037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
33710037SARM gem5 Developers    } else {
33810037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
33910037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
34010037SARM gem5 Developers    }
34110037SARM gem5 Developers    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
34210037SARM gem5 Developers
34310037SARM gem5 Developers    microOps[0]->setDelayedCommit();
34410037SARM gem5 Developers    microOps[1]->setDelayedCommit();
34510037SARM gem5 Developers    microOps[2]->setLastMicroop();
34610037SARM gem5 Developers}
34710037SARM gem5 Developers
34810037SARM gem5 DevelopersBigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst,
34910037SARM gem5 Developers                             OpClass __opClass, bool load, IntRegIndex dest,
35010037SARM gem5 Developers                             IntRegIndex base, IntRegIndex offset,
35110037SARM gem5 Developers                             ArmExtendType type, int64_t imm) :
35210037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
35310037SARM gem5 Developers{
35410037SARM gem5 Developers    numMicroops = 2;
35510037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
35610037SARM gem5 Developers
35710037SARM gem5 Developers    if (load) {
35810037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXRegUop(machInst, dest, base,
35910037SARM gem5 Developers                                              offset, type, imm);
36010037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXRegUop(machInst, dest, base,
36110037SARM gem5 Developers                                              offset, type, imm);
36210037SARM gem5 Developers    } else {
36310037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXRegUop(machInst, dest, base,
36410037SARM gem5 Developers                                              offset, type, imm);
36510037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXRegUop(machInst, dest, base,
36610037SARM gem5 Developers                                              offset, type, imm);
36710037SARM gem5 Developers    }
36810037SARM gem5 Developers
36910037SARM gem5 Developers    microOps[0]->setDelayedCommit();
37010037SARM gem5 Developers    microOps[1]->setLastMicroop();
37110037SARM gem5 Developers}
37210037SARM gem5 Developers
37310037SARM gem5 DevelopersBigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst,
37410037SARM gem5 Developers                             OpClass __opClass, IntRegIndex dest,
37510037SARM gem5 Developers                             int64_t imm) :
37610037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
37710037SARM gem5 Developers{
37810037SARM gem5 Developers    numMicroops = 2;
37910037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
38010037SARM gem5 Developers
38110037SARM gem5 Developers    microOps[0] = new MicroLdrQBFpXLitUop(machInst, dest, imm);
38210037SARM gem5 Developers    microOps[1] = new MicroLdrQTFpXLitUop(machInst, dest, imm);
38310037SARM gem5 Developers
38410037SARM gem5 Developers    microOps[0]->setDelayedCommit();
38510037SARM gem5 Developers    microOps[1]->setLastMicroop();
38610037SARM gem5 Developers}
38710037SARM gem5 Developers
3887639Sgblack@eecs.umich.eduVldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
3897639Sgblack@eecs.umich.edu                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
3907639Sgblack@eecs.umich.edu                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
3917639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
3927639Sgblack@eecs.umich.edu{
3937639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
3947639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
3957639Sgblack@eecs.umich.edu
3967639Sgblack@eecs.umich.edu    numMicroops = (regs > 2) ? 2 : 1;
3977639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
3987639Sgblack@eecs.umich.edu    bool deinterleave = (elems > 1);
3997639Sgblack@eecs.umich.edu
4007639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
4017639Sgblack@eecs.umich.edu    if (deinterleave) numMicroops += (regs / elems);
4027639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
4037639Sgblack@eecs.umich.edu
40410037SARM gem5 Developers    RegIndex rMid = deinterleave ? NumFloatV7ArchRegs : vd * 2;
4057639Sgblack@eecs.umich.edu
4067639Sgblack@eecs.umich.edu    uint32_t noAlign = TLB::MustBeOne;
4077639Sgblack@eecs.umich.edu
4087639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
4097639Sgblack@eecs.umich.edu    switch (regs) {
4107639Sgblack@eecs.umich.edu      case 4:
4117639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4127639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4137639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4147639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
4157639Sgblack@eecs.umich.edu        break;
4167639Sgblack@eecs.umich.edu      case 3:
4177639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4187639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4197639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
4207639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
4217639Sgblack@eecs.umich.edu        break;
4227639Sgblack@eecs.umich.edu      case 2:
4237639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4247639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4257639Sgblack@eecs.umich.edu        break;
4267639Sgblack@eecs.umich.edu      case 1:
4277639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
4287639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4297639Sgblack@eecs.umich.edu        break;
4307639Sgblack@eecs.umich.edu      default:
4317853SMatt.Horsnell@ARM.com        // Unknown number of registers
4327853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
4337639Sgblack@eecs.umich.edu    }
4347639Sgblack@eecs.umich.edu    if (wb) {
4357639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
4367639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
4377646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
4387639Sgblack@eecs.umich.edu        } else {
4397639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
4407639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, regs * 8);
4417639Sgblack@eecs.umich.edu        }
4427639Sgblack@eecs.umich.edu    }
4437639Sgblack@eecs.umich.edu    if (deinterleave) {
4447639Sgblack@eecs.umich.edu        switch (elems) {
4457639Sgblack@eecs.umich.edu          case 4:
4467639Sgblack@eecs.umich.edu            assert(regs == 4);
4477639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>(
4487639Sgblack@eecs.umich.edu                    size, machInst, vd * 2, rMid, inc * 2);
4497639Sgblack@eecs.umich.edu            break;
4507639Sgblack@eecs.umich.edu          case 3:
4517639Sgblack@eecs.umich.edu            assert(regs == 3);
4527639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>(
4537639Sgblack@eecs.umich.edu                    size, machInst, vd * 2, rMid, inc * 2);
4547639Sgblack@eecs.umich.edu            break;
4557639Sgblack@eecs.umich.edu          case 2:
4567639Sgblack@eecs.umich.edu            assert(regs == 4 || regs == 2);
4577639Sgblack@eecs.umich.edu            if (regs == 4) {
4587639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4597639Sgblack@eecs.umich.edu                        size, machInst, vd * 2, rMid, inc * 2);
4607639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4617639Sgblack@eecs.umich.edu                        size, machInst, vd * 2 + 2, rMid + 4, inc * 2);
4627639Sgblack@eecs.umich.edu            } else {
4637639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4647639Sgblack@eecs.umich.edu                        size, machInst, vd * 2, rMid, inc * 2);
4657639Sgblack@eecs.umich.edu            }
4667639Sgblack@eecs.umich.edu            break;
4677639Sgblack@eecs.umich.edu          default:
4687853SMatt.Horsnell@ARM.com            // Bad number of elements to deinterleave
4697853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
4707639Sgblack@eecs.umich.edu        }
4717639Sgblack@eecs.umich.edu    }
4727639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
4737639Sgblack@eecs.umich.edu
4747639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
4757639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
4767639Sgblack@eecs.umich.edu        assert(uopPtr);
4777639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
4787639Sgblack@eecs.umich.edu    }
4797639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
4807639Sgblack@eecs.umich.edu}
4817639Sgblack@eecs.umich.edu
4827639Sgblack@eecs.umich.eduVldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
4837639Sgblack@eecs.umich.edu                         OpClass __opClass, bool all, unsigned elems,
4847639Sgblack@eecs.umich.edu                         RegIndex rn, RegIndex vd, unsigned regs,
4857639Sgblack@eecs.umich.edu                         unsigned inc, uint32_t size, uint32_t align,
4867639Sgblack@eecs.umich.edu                         RegIndex rm, unsigned lane) :
4877639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
4887639Sgblack@eecs.umich.edu{
4897639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
4907639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
4917639Sgblack@eecs.umich.edu
4927639Sgblack@eecs.umich.edu    unsigned eBytes = (1 << size);
4937639Sgblack@eecs.umich.edu    unsigned loadSize = eBytes * elems;
4947639Sgblack@eecs.umich.edu    unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) /
4957639Sgblack@eecs.umich.edu                        sizeof(FloatRegBits);
4967639Sgblack@eecs.umich.edu
4977639Sgblack@eecs.umich.edu    assert(loadRegs > 0 && loadRegs <= 4);
4987639Sgblack@eecs.umich.edu
4997639Sgblack@eecs.umich.edu    numMicroops = 1;
5007639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
5017639Sgblack@eecs.umich.edu
5027639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
5037639Sgblack@eecs.umich.edu    numMicroops += (regs / elems);
5047639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
5057639Sgblack@eecs.umich.edu
50610037SARM gem5 Developers    RegIndex ufp0 = NumFloatV7ArchRegs;
5077639Sgblack@eecs.umich.edu
5087639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
5097639Sgblack@eecs.umich.edu    switch (loadSize) {
5107639Sgblack@eecs.umich.edu      case 1:
5117639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>(
5127639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5137639Sgblack@eecs.umich.edu        break;
5147639Sgblack@eecs.umich.edu      case 2:
5157639Sgblack@eecs.umich.edu        if (eBytes == 2) {
5167639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>(
5177639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5187639Sgblack@eecs.umich.edu        } else {
5197639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>(
5207639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5217639Sgblack@eecs.umich.edu        }
5227639Sgblack@eecs.umich.edu        break;
5237639Sgblack@eecs.umich.edu      case 3:
5247639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>(
5257639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5267639Sgblack@eecs.umich.edu        break;
5277639Sgblack@eecs.umich.edu      case 4:
5287639Sgblack@eecs.umich.edu        switch (eBytes) {
5297639Sgblack@eecs.umich.edu          case 1:
5307639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>(
5317639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5327639Sgblack@eecs.umich.edu            break;
5337639Sgblack@eecs.umich.edu          case 2:
5347639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>(
5357639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5367639Sgblack@eecs.umich.edu            break;
5377639Sgblack@eecs.umich.edu          case 4:
5387639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>(
5397639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5407639Sgblack@eecs.umich.edu            break;
5417639Sgblack@eecs.umich.edu        }
5427639Sgblack@eecs.umich.edu        break;
5437639Sgblack@eecs.umich.edu      case 6:
5447639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>(
5457639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5467639Sgblack@eecs.umich.edu        break;
5477639Sgblack@eecs.umich.edu      case 8:
5487639Sgblack@eecs.umich.edu        switch (eBytes) {
5497639Sgblack@eecs.umich.edu          case 2:
5507639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>(
5517639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5527639Sgblack@eecs.umich.edu            break;
5537639Sgblack@eecs.umich.edu          case 4:
5547639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>(
5557639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5567639Sgblack@eecs.umich.edu            break;
5577639Sgblack@eecs.umich.edu        }
5587639Sgblack@eecs.umich.edu        break;
5597639Sgblack@eecs.umich.edu      case 12:
5607639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>(
5617639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5627639Sgblack@eecs.umich.edu        break;
5637639Sgblack@eecs.umich.edu      case 16:
5647639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>(
5657639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5667639Sgblack@eecs.umich.edu        break;
5677639Sgblack@eecs.umich.edu      default:
5687853SMatt.Horsnell@ARM.com        // Unrecognized load size
5697853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
5707639Sgblack@eecs.umich.edu    }
5717639Sgblack@eecs.umich.edu    if (wb) {
5727639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
5737639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
5747646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
5757639Sgblack@eecs.umich.edu        } else {
5767639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
5777639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, loadSize);
5787639Sgblack@eecs.umich.edu        }
5797639Sgblack@eecs.umich.edu    }
5807639Sgblack@eecs.umich.edu    switch (elems) {
5817639Sgblack@eecs.umich.edu      case 4:
5827639Sgblack@eecs.umich.edu        assert(regs == 4);
5837639Sgblack@eecs.umich.edu        switch (size) {
5847639Sgblack@eecs.umich.edu          case 0:
5857639Sgblack@eecs.umich.edu            if (all) {
5867639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>(
5877639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
5887639Sgblack@eecs.umich.edu            } else {
5897639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>(
5907639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
5917639Sgblack@eecs.umich.edu            }
5927639Sgblack@eecs.umich.edu            break;
5937639Sgblack@eecs.umich.edu          case 1:
5947639Sgblack@eecs.umich.edu            if (all) {
5957639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>(
5967639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
5977639Sgblack@eecs.umich.edu            } else {
5987639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>(
5997639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6007639Sgblack@eecs.umich.edu            }
6017639Sgblack@eecs.umich.edu            break;
6027639Sgblack@eecs.umich.edu          case 2:
6037639Sgblack@eecs.umich.edu            if (all) {
6047639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>(
6057639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6067639Sgblack@eecs.umich.edu            } else {
6077639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>(
6087639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6097639Sgblack@eecs.umich.edu            }
6107639Sgblack@eecs.umich.edu            break;
6117639Sgblack@eecs.umich.edu          default:
6127853SMatt.Horsnell@ARM.com            // Bad size
6137853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
6147639Sgblack@eecs.umich.edu            break;
6157639Sgblack@eecs.umich.edu        }
6167639Sgblack@eecs.umich.edu        break;
6177639Sgblack@eecs.umich.edu      case 3:
6187639Sgblack@eecs.umich.edu        assert(regs == 3);
6197639Sgblack@eecs.umich.edu        switch (size) {
6207639Sgblack@eecs.umich.edu          case 0:
6217639Sgblack@eecs.umich.edu            if (all) {
6227639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>(
6237639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6247639Sgblack@eecs.umich.edu            } else {
6257639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>(
6267639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6277639Sgblack@eecs.umich.edu            }
6287639Sgblack@eecs.umich.edu            break;
6297639Sgblack@eecs.umich.edu          case 1:
6307639Sgblack@eecs.umich.edu            if (all) {
6317639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>(
6327639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6337639Sgblack@eecs.umich.edu            } else {
6347639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>(
6357639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6367639Sgblack@eecs.umich.edu            }
6377639Sgblack@eecs.umich.edu            break;
6387639Sgblack@eecs.umich.edu          case 2:
6397639Sgblack@eecs.umich.edu            if (all) {
6407639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>(
6417639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6427639Sgblack@eecs.umich.edu            } else {
6437639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>(
6447639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6457639Sgblack@eecs.umich.edu            }
6467639Sgblack@eecs.umich.edu            break;
6477639Sgblack@eecs.umich.edu          default:
6487853SMatt.Horsnell@ARM.com            // Bad size
6497853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
6507639Sgblack@eecs.umich.edu            break;
6517639Sgblack@eecs.umich.edu        }
6527639Sgblack@eecs.umich.edu        break;
6537639Sgblack@eecs.umich.edu      case 2:
6547639Sgblack@eecs.umich.edu        assert(regs == 2);
6557639Sgblack@eecs.umich.edu        assert(loadRegs <= 2);
6567639Sgblack@eecs.umich.edu        switch (size) {
6577639Sgblack@eecs.umich.edu          case 0:
6587639Sgblack@eecs.umich.edu            if (all) {
6597639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>(
6607639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6617639Sgblack@eecs.umich.edu            } else {
6627639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>(
6637639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6647639Sgblack@eecs.umich.edu            }
6657639Sgblack@eecs.umich.edu            break;
6667639Sgblack@eecs.umich.edu          case 1:
6677639Sgblack@eecs.umich.edu            if (all) {
6687639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>(
6697639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6707639Sgblack@eecs.umich.edu            } else {
6717639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>(
6727639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6737639Sgblack@eecs.umich.edu            }
6747639Sgblack@eecs.umich.edu            break;
6757639Sgblack@eecs.umich.edu          case 2:
6767639Sgblack@eecs.umich.edu            if (all) {
6777639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>(
6787639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6797639Sgblack@eecs.umich.edu            } else {
6807639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>(
6817639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6827639Sgblack@eecs.umich.edu            }
6837639Sgblack@eecs.umich.edu            break;
6847639Sgblack@eecs.umich.edu          default:
6857853SMatt.Horsnell@ARM.com            // Bad size
6867853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
6877639Sgblack@eecs.umich.edu            break;
6887639Sgblack@eecs.umich.edu        }
6897639Sgblack@eecs.umich.edu        break;
6907639Sgblack@eecs.umich.edu      case 1:
6917639Sgblack@eecs.umich.edu        assert(regs == 1 || (all && regs == 2));
6927639Sgblack@eecs.umich.edu        assert(loadRegs <= 2);
6937639Sgblack@eecs.umich.edu        for (unsigned offset = 0; offset < regs; offset++) {
6947639Sgblack@eecs.umich.edu            switch (size) {
6957639Sgblack@eecs.umich.edu              case 0:
6967639Sgblack@eecs.umich.edu                if (all) {
6977639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
6987639Sgblack@eecs.umich.edu                        new MicroUnpackAllNeon2to2Uop<uint8_t>(
6997639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2);
7007639Sgblack@eecs.umich.edu                } else {
7017639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7027639Sgblack@eecs.umich.edu                        new MicroUnpackNeon2to2Uop<uint8_t>(
7037639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
7047639Sgblack@eecs.umich.edu                }
7057639Sgblack@eecs.umich.edu                break;
7067639Sgblack@eecs.umich.edu              case 1:
7077639Sgblack@eecs.umich.edu                if (all) {
7087639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7097639Sgblack@eecs.umich.edu                        new MicroUnpackAllNeon2to2Uop<uint16_t>(
7107639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2);
7117639Sgblack@eecs.umich.edu                } else {
7127639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7137639Sgblack@eecs.umich.edu                        new MicroUnpackNeon2to2Uop<uint16_t>(
7147639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
7157639Sgblack@eecs.umich.edu                }
7167639Sgblack@eecs.umich.edu                break;
7177639Sgblack@eecs.umich.edu              case 2:
7187639Sgblack@eecs.umich.edu                if (all) {
7197639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7207639Sgblack@eecs.umich.edu                        new MicroUnpackAllNeon2to2Uop<uint32_t>(
7217639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2);
7227639Sgblack@eecs.umich.edu                } else {
7237639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7247639Sgblack@eecs.umich.edu                        new MicroUnpackNeon2to2Uop<uint32_t>(
7257639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
7267639Sgblack@eecs.umich.edu                }
7277639Sgblack@eecs.umich.edu                break;
7287639Sgblack@eecs.umich.edu              default:
7297853SMatt.Horsnell@ARM.com                // Bad size
7307853SMatt.Horsnell@ARM.com                microOps[uopIdx++] = new Unknown(machInst);
7317639Sgblack@eecs.umich.edu                break;
7327639Sgblack@eecs.umich.edu            }
7337639Sgblack@eecs.umich.edu        }
7347639Sgblack@eecs.umich.edu        break;
7357639Sgblack@eecs.umich.edu      default:
7367853SMatt.Horsnell@ARM.com        // Bad number of elements to unpack
7377853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
7387639Sgblack@eecs.umich.edu    }
7397639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
7407639Sgblack@eecs.umich.edu
7417639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
7427639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
7437639Sgblack@eecs.umich.edu        assert(uopPtr);
7447639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
7457639Sgblack@eecs.umich.edu    }
7467639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
7477639Sgblack@eecs.umich.edu}
7487639Sgblack@eecs.umich.edu
7497639Sgblack@eecs.umich.eduVstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
7507639Sgblack@eecs.umich.edu                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
7517639Sgblack@eecs.umich.edu                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
7527639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
7537639Sgblack@eecs.umich.edu{
7547639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
7557639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
7567639Sgblack@eecs.umich.edu
7577639Sgblack@eecs.umich.edu    numMicroops = (regs > 2) ? 2 : 1;
7587639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
7597639Sgblack@eecs.umich.edu    bool interleave = (elems > 1);
7607639Sgblack@eecs.umich.edu
7617639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
7627639Sgblack@eecs.umich.edu    if (interleave) numMicroops += (regs / elems);
7637639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
7647639Sgblack@eecs.umich.edu
7657639Sgblack@eecs.umich.edu    uint32_t noAlign = TLB::MustBeOne;
7667639Sgblack@eecs.umich.edu
76710037SARM gem5 Developers    RegIndex rMid = interleave ? NumFloatV7ArchRegs : vd * 2;
7687639Sgblack@eecs.umich.edu
7697639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
7707639Sgblack@eecs.umich.edu    if (interleave) {
7717639Sgblack@eecs.umich.edu        switch (elems) {
7727639Sgblack@eecs.umich.edu          case 4:
7737639Sgblack@eecs.umich.edu            assert(regs == 4);
7747639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>(
7757639Sgblack@eecs.umich.edu                    size, machInst, rMid, vd * 2, inc * 2);
7767639Sgblack@eecs.umich.edu            break;
7777639Sgblack@eecs.umich.edu          case 3:
7787639Sgblack@eecs.umich.edu            assert(regs == 3);
7797639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>(
7807639Sgblack@eecs.umich.edu                    size, machInst, rMid, vd * 2, inc * 2);
7817639Sgblack@eecs.umich.edu            break;
7827639Sgblack@eecs.umich.edu          case 2:
7837639Sgblack@eecs.umich.edu            assert(regs == 4 || regs == 2);
7847639Sgblack@eecs.umich.edu            if (regs == 4) {
7857639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
7867639Sgblack@eecs.umich.edu                        size, machInst, rMid, vd * 2, inc * 2);
7877639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
7887639Sgblack@eecs.umich.edu                        size, machInst, rMid + 4, vd * 2 + 2, inc * 2);
7897639Sgblack@eecs.umich.edu            } else {
7907639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
7917639Sgblack@eecs.umich.edu                        size, machInst, rMid, vd * 2, inc * 2);
7927639Sgblack@eecs.umich.edu            }
7937639Sgblack@eecs.umich.edu            break;
7947639Sgblack@eecs.umich.edu          default:
7957853SMatt.Horsnell@ARM.com            // Bad number of elements to interleave
7967853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
7977639Sgblack@eecs.umich.edu        }
7987639Sgblack@eecs.umich.edu    }
7997639Sgblack@eecs.umich.edu    switch (regs) {
8007639Sgblack@eecs.umich.edu      case 4:
8017639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8027639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8037639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8047639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
8057639Sgblack@eecs.umich.edu        break;
8067639Sgblack@eecs.umich.edu      case 3:
8077639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8087639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8097639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
8107639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
8117639Sgblack@eecs.umich.edu        break;
8127639Sgblack@eecs.umich.edu      case 2:
8137639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8147639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8157639Sgblack@eecs.umich.edu        break;
8167639Sgblack@eecs.umich.edu      case 1:
8177639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
8187639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8197639Sgblack@eecs.umich.edu        break;
8207639Sgblack@eecs.umich.edu      default:
8217853SMatt.Horsnell@ARM.com        // Unknown number of registers
8227853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
8237639Sgblack@eecs.umich.edu    }
8247639Sgblack@eecs.umich.edu    if (wb) {
8257639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
8267639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
8277646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
8287639Sgblack@eecs.umich.edu        } else {
8297639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
8307639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, regs * 8);
8317639Sgblack@eecs.umich.edu        }
8327639Sgblack@eecs.umich.edu    }
8337639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
8347639Sgblack@eecs.umich.edu
8357639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
8367639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
8377639Sgblack@eecs.umich.edu        assert(uopPtr);
8387639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
8397639Sgblack@eecs.umich.edu    }
8407639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
8417639Sgblack@eecs.umich.edu}
8427639Sgblack@eecs.umich.edu
8437639Sgblack@eecs.umich.eduVstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
8447639Sgblack@eecs.umich.edu                         OpClass __opClass, bool all, unsigned elems,
8457639Sgblack@eecs.umich.edu                         RegIndex rn, RegIndex vd, unsigned regs,
8467639Sgblack@eecs.umich.edu                         unsigned inc, uint32_t size, uint32_t align,
8477639Sgblack@eecs.umich.edu                         RegIndex rm, unsigned lane) :
8487639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
8497639Sgblack@eecs.umich.edu{
8507639Sgblack@eecs.umich.edu    assert(!all);
8517639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
8527639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
8537639Sgblack@eecs.umich.edu
8547639Sgblack@eecs.umich.edu    unsigned eBytes = (1 << size);
8557639Sgblack@eecs.umich.edu    unsigned storeSize = eBytes * elems;
8567639Sgblack@eecs.umich.edu    unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) /
8577639Sgblack@eecs.umich.edu                         sizeof(FloatRegBits);
8587639Sgblack@eecs.umich.edu
8597639Sgblack@eecs.umich.edu    assert(storeRegs > 0 && storeRegs <= 4);
8607639Sgblack@eecs.umich.edu
8617639Sgblack@eecs.umich.edu    numMicroops = 1;
8627639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
8637639Sgblack@eecs.umich.edu
8647639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
8657639Sgblack@eecs.umich.edu    numMicroops += (regs / elems);
8667639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
8677639Sgblack@eecs.umich.edu
86810037SARM gem5 Developers    RegIndex ufp0 = NumFloatV7ArchRegs;
8697639Sgblack@eecs.umich.edu
8707639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
8717639Sgblack@eecs.umich.edu    switch (elems) {
8727639Sgblack@eecs.umich.edu      case 4:
8737639Sgblack@eecs.umich.edu        assert(regs == 4);
8747639Sgblack@eecs.umich.edu        switch (size) {
8757639Sgblack@eecs.umich.edu          case 0:
8767639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>(
8777639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8787639Sgblack@eecs.umich.edu            break;
8797639Sgblack@eecs.umich.edu          case 1:
8807639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>(
8817639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8827639Sgblack@eecs.umich.edu            break;
8837639Sgblack@eecs.umich.edu          case 2:
8847639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>(
8857639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8867639Sgblack@eecs.umich.edu            break;
8877639Sgblack@eecs.umich.edu          default:
8887853SMatt.Horsnell@ARM.com            // Bad size
8897853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
8907639Sgblack@eecs.umich.edu            break;
8917639Sgblack@eecs.umich.edu        }
8927639Sgblack@eecs.umich.edu        break;
8937639Sgblack@eecs.umich.edu      case 3:
8947639Sgblack@eecs.umich.edu        assert(regs == 3);
8957639Sgblack@eecs.umich.edu        switch (size) {
8967639Sgblack@eecs.umich.edu          case 0:
8977639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>(
8987639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8997639Sgblack@eecs.umich.edu            break;
9007639Sgblack@eecs.umich.edu          case 1:
9017639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>(
9027639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9037639Sgblack@eecs.umich.edu            break;
9047639Sgblack@eecs.umich.edu          case 2:
9057639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>(
9067639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9077639Sgblack@eecs.umich.edu            break;
9087639Sgblack@eecs.umich.edu          default:
9097853SMatt.Horsnell@ARM.com            // Bad size
9107853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
9117639Sgblack@eecs.umich.edu            break;
9127639Sgblack@eecs.umich.edu        }
9137639Sgblack@eecs.umich.edu        break;
9147639Sgblack@eecs.umich.edu      case 2:
9157639Sgblack@eecs.umich.edu        assert(regs == 2);
9167639Sgblack@eecs.umich.edu        assert(storeRegs <= 2);
9177639Sgblack@eecs.umich.edu        switch (size) {
9187639Sgblack@eecs.umich.edu          case 0:
9197639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>(
9207639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9217639Sgblack@eecs.umich.edu            break;
9227639Sgblack@eecs.umich.edu          case 1:
9237639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>(
9247639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9257639Sgblack@eecs.umich.edu            break;
9267639Sgblack@eecs.umich.edu          case 2:
9277639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>(
9287639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9297639Sgblack@eecs.umich.edu            break;
9307639Sgblack@eecs.umich.edu          default:
9317853SMatt.Horsnell@ARM.com            // Bad size
9327853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
9337639Sgblack@eecs.umich.edu            break;
9347639Sgblack@eecs.umich.edu        }
9357639Sgblack@eecs.umich.edu        break;
9367639Sgblack@eecs.umich.edu      case 1:
9377639Sgblack@eecs.umich.edu        assert(regs == 1 || (all && regs == 2));
9387639Sgblack@eecs.umich.edu        assert(storeRegs <= 2);
9397639Sgblack@eecs.umich.edu        for (unsigned offset = 0; offset < regs; offset++) {
9407639Sgblack@eecs.umich.edu            switch (size) {
9417639Sgblack@eecs.umich.edu              case 0:
9427639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>(
9437639Sgblack@eecs.umich.edu                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
9447639Sgblack@eecs.umich.edu                break;
9457639Sgblack@eecs.umich.edu              case 1:
9467639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>(
9477639Sgblack@eecs.umich.edu                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
9487639Sgblack@eecs.umich.edu                break;
9497639Sgblack@eecs.umich.edu              case 2:
9507639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>(
9517639Sgblack@eecs.umich.edu                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
9527639Sgblack@eecs.umich.edu                break;
9537639Sgblack@eecs.umich.edu              default:
9547853SMatt.Horsnell@ARM.com                // Bad size
9557853SMatt.Horsnell@ARM.com                microOps[uopIdx++] = new Unknown(machInst);
9567639Sgblack@eecs.umich.edu                break;
9577639Sgblack@eecs.umich.edu            }
9587639Sgblack@eecs.umich.edu        }
9597639Sgblack@eecs.umich.edu        break;
9607639Sgblack@eecs.umich.edu      default:
9617853SMatt.Horsnell@ARM.com        // Bad number of elements to unpack
9627853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
9637639Sgblack@eecs.umich.edu    }
9647639Sgblack@eecs.umich.edu    switch (storeSize) {
9657639Sgblack@eecs.umich.edu      case 1:
9667639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>(
9677639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
9687639Sgblack@eecs.umich.edu        break;
9697639Sgblack@eecs.umich.edu      case 2:
9707639Sgblack@eecs.umich.edu        if (eBytes == 2) {
9717639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>(
9727639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9737639Sgblack@eecs.umich.edu        } else {
9747639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>(
9757639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9767639Sgblack@eecs.umich.edu        }
9777639Sgblack@eecs.umich.edu        break;
9787639Sgblack@eecs.umich.edu      case 3:
9797639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>(
9807639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
9817639Sgblack@eecs.umich.edu        break;
9827639Sgblack@eecs.umich.edu      case 4:
9837639Sgblack@eecs.umich.edu        switch (eBytes) {
9847639Sgblack@eecs.umich.edu          case 1:
9857639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>(
9867639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9877639Sgblack@eecs.umich.edu            break;
9887639Sgblack@eecs.umich.edu          case 2:
9897639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>(
9907639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9917639Sgblack@eecs.umich.edu            break;
9927639Sgblack@eecs.umich.edu          case 4:
9937639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>(
9947639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9957639Sgblack@eecs.umich.edu            break;
9967639Sgblack@eecs.umich.edu        }
9977639Sgblack@eecs.umich.edu        break;
9987639Sgblack@eecs.umich.edu      case 6:
9997639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>(
10007639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10017639Sgblack@eecs.umich.edu        break;
10027639Sgblack@eecs.umich.edu      case 8:
10037639Sgblack@eecs.umich.edu        switch (eBytes) {
10047639Sgblack@eecs.umich.edu          case 2:
10057639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>(
10067639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10077639Sgblack@eecs.umich.edu            break;
10087639Sgblack@eecs.umich.edu          case 4:
10097639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>(
10107639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10117639Sgblack@eecs.umich.edu            break;
10127639Sgblack@eecs.umich.edu        }
10137639Sgblack@eecs.umich.edu        break;
10147639Sgblack@eecs.umich.edu      case 12:
10157639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>(
10167639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10177639Sgblack@eecs.umich.edu        break;
10187639Sgblack@eecs.umich.edu      case 16:
10197639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>(
10207639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10217639Sgblack@eecs.umich.edu        break;
10227639Sgblack@eecs.umich.edu      default:
10237853SMatt.Horsnell@ARM.com        // Bad store size
10247853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
10257639Sgblack@eecs.umich.edu    }
10267639Sgblack@eecs.umich.edu    if (wb) {
10277639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
10287639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
10297646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
10307639Sgblack@eecs.umich.edu        } else {
10317639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
10327639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, storeSize);
10337639Sgblack@eecs.umich.edu        }
10347639Sgblack@eecs.umich.edu    }
10357639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
10367639Sgblack@eecs.umich.edu
10377639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
10387639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
10397639Sgblack@eecs.umich.edu        assert(uopPtr);
10407639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
10417639Sgblack@eecs.umich.edu    }
10427639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
10437639Sgblack@eecs.umich.edu}
10447639Sgblack@eecs.umich.edu
104510037SARM gem5 DevelopersVldMultOp64::VldMultOp64(const char *mnem, ExtMachInst machInst,
104610037SARM gem5 Developers                         OpClass __opClass, RegIndex rn, RegIndex vd,
104710037SARM gem5 Developers                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
104810037SARM gem5 Developers                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
104910037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
105010037SARM gem5 Developers{
105110037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
105210037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
105310037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
105410037SARM gem5 Developers
105510037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
105610037SARM gem5 Developers
105710037SARM gem5 Developers    int totNumBytes = numRegs * dataSize / 8;
105810037SARM gem5 Developers    assert(totNumBytes <= 64);
105910037SARM gem5 Developers
106010037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
106110037SARM gem5 Developers    // transferred at a time
106210037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
106310037SARM gem5 Developers    int residuum = totNumBytes % 16;
106410037SARM gem5 Developers    if (residuum)
106510037SARM gem5 Developers        ++numMemMicroops;
106610037SARM gem5 Developers    numMicroops += numMemMicroops;
106710037SARM gem5 Developers
106810037SARM gem5 Developers    int numMarshalMicroops = numRegs / 2 + (numRegs % 2 ? 1 : 0);
106910037SARM gem5 Developers    numMicroops += numMarshalMicroops;
107010037SARM gem5 Developers
107110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
107210037SARM gem5 Developers    unsigned uopIdx = 0;
107310037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
107410037SARM gem5 Developers        TLB::AllowUnaligned;
107510037SARM gem5 Developers
107610037SARM gem5 Developers    int i = 0;
107710037SARM gem5 Developers    for(; i < numMemMicroops - 1; ++i) {
107810037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonLoad64(
107910037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
108010037SARM gem5 Developers            baseIsSP, 16 /* accSize */, eSize);
108110037SARM gem5 Developers    }
108210037SARM gem5 Developers    microOps[uopIdx++] =  new MicroNeonLoad64(
108310037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
108410037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
108510037SARM gem5 Developers
108610037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
108710037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
108810037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
108910037SARM gem5 Developers    if (wb) {
109010037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
109110037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
109210037SARM gem5 Developers                                                      UXTX, 0);
109310037SARM gem5 Developers        } else {
109410037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
109510037SARM gem5 Developers                                                   totNumBytes);
109610037SARM gem5 Developers        }
109710037SARM gem5 Developers    }
109810037SARM gem5 Developers
109910037SARM gem5 Developers    for (int i = 0; i < numMarshalMicroops; ++i) {
110010037SARM gem5 Developers        microOps[uopIdx++] = new MicroDeintNeon64(
110110037SARM gem5 Developers            machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
110210037SARM gem5 Developers            numStructElems, numRegs, i /* step */);
110310037SARM gem5 Developers    }
110410037SARM gem5 Developers
110510037SARM gem5 Developers    assert(uopIdx == numMicroops);
110610037SARM gem5 Developers
110710037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; ++i) {
110810037SARM gem5 Developers        microOps[i]->setDelayedCommit();
110910037SARM gem5 Developers    }
111010037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
111110037SARM gem5 Developers}
111210037SARM gem5 Developers
111310037SARM gem5 DevelopersVstMultOp64::VstMultOp64(const char *mnem, ExtMachInst machInst,
111410037SARM gem5 Developers                         OpClass __opClass, RegIndex rn, RegIndex vd,
111510037SARM gem5 Developers                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
111610037SARM gem5 Developers                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
111710037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
111810037SARM gem5 Developers{
111910037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
112010037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
112110037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
112210037SARM gem5 Developers
112310037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
112410037SARM gem5 Developers
112510037SARM gem5 Developers    int totNumBytes = numRegs * dataSize / 8;
112610037SARM gem5 Developers    assert(totNumBytes <= 64);
112710037SARM gem5 Developers
112810037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
112910037SARM gem5 Developers    // transferred at a time
113010037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
113110037SARM gem5 Developers    int residuum = totNumBytes % 16;
113210037SARM gem5 Developers    if (residuum)
113310037SARM gem5 Developers        ++numMemMicroops;
113410037SARM gem5 Developers    numMicroops += numMemMicroops;
113510037SARM gem5 Developers
113610037SARM gem5 Developers    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
113710037SARM gem5 Developers    numMicroops += numMarshalMicroops;
113810037SARM gem5 Developers
113910037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
114010037SARM gem5 Developers    unsigned uopIdx = 0;
114110037SARM gem5 Developers
114210037SARM gem5 Developers    for(int i = 0; i < numMarshalMicroops; ++i) {
114310037SARM gem5 Developers        microOps[uopIdx++] = new MicroIntNeon64(
114410037SARM gem5 Developers            machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
114510037SARM gem5 Developers            numStructElems, numRegs, i /* step */);
114610037SARM gem5 Developers    }
114710037SARM gem5 Developers
114810037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
114910037SARM gem5 Developers        TLB::AllowUnaligned;
115010037SARM gem5 Developers
115110037SARM gem5 Developers    int i = 0;
115210037SARM gem5 Developers    for(; i < numMemMicroops - 1; ++i) {
115310037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonStore64(
115410037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
115510037SARM gem5 Developers            baseIsSP, 16 /* accSize */, eSize);
115610037SARM gem5 Developers    }
115710037SARM gem5 Developers    microOps[uopIdx++] = new MicroNeonStore64(
115810037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
115910037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
116010037SARM gem5 Developers
116110037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
116210037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
116310037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
116410037SARM gem5 Developers    if (wb) {
116510037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
116610037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
116710037SARM gem5 Developers                                                      UXTX, 0);
116810037SARM gem5 Developers        } else {
116910037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
117010037SARM gem5 Developers                                                   totNumBytes);
117110037SARM gem5 Developers        }
117210037SARM gem5 Developers    }
117310037SARM gem5 Developers
117410037SARM gem5 Developers    assert(uopIdx == numMicroops);
117510037SARM gem5 Developers
117610037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; i++) {
117710037SARM gem5 Developers        microOps[i]->setDelayedCommit();
117810037SARM gem5 Developers    }
117910037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
118010037SARM gem5 Developers}
118110037SARM gem5 Developers
118210037SARM gem5 DevelopersVldSingleOp64::VldSingleOp64(const char *mnem, ExtMachInst machInst,
118310037SARM gem5 Developers                             OpClass __opClass, RegIndex rn, RegIndex vd,
118410037SARM gem5 Developers                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
118510037SARM gem5 Developers                             uint8_t numStructElems, uint8_t index, bool wb,
118610037SARM gem5 Developers                             bool replicate) :
118710037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
118810037SARM gem5 Developers{
118910037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
119010037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
119110037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
119210037SARM gem5 Developers
119310037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
119410037SARM gem5 Developers
119510037SARM gem5 Developers    int eSizeBytes = 1 << eSize;
119610037SARM gem5 Developers    int totNumBytes = numStructElems * eSizeBytes;
119710037SARM gem5 Developers    assert(totNumBytes <= 64);
119810037SARM gem5 Developers
119910037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
120010037SARM gem5 Developers    // transferred at a time
120110037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
120210037SARM gem5 Developers    int residuum = totNumBytes % 16;
120310037SARM gem5 Developers    if (residuum)
120410037SARM gem5 Developers        ++numMemMicroops;
120510037SARM gem5 Developers    numMicroops += numMemMicroops;
120610037SARM gem5 Developers
120710037SARM gem5 Developers    int numMarshalMicroops = numStructElems / 2 + (numStructElems % 2 ? 1 : 0);
120810037SARM gem5 Developers    numMicroops += numMarshalMicroops;
120910037SARM gem5 Developers
121010037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
121110037SARM gem5 Developers    unsigned uopIdx = 0;
121210037SARM gem5 Developers
121310037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
121410037SARM gem5 Developers        TLB::AllowUnaligned;
121510037SARM gem5 Developers
121610037SARM gem5 Developers    int i = 0;
121710037SARM gem5 Developers    for (; i < numMemMicroops - 1; ++i) {
121810037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonLoad64(
121910037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
122010037SARM gem5 Developers            baseIsSP, 16 /* accSize */, eSize);
122110037SARM gem5 Developers    }
122210037SARM gem5 Developers    microOps[uopIdx++] = new MicroNeonLoad64(
122310037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
122410037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
122510037SARM gem5 Developers
122610037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
122710037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
122810037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
122910037SARM gem5 Developers    if (wb) {
123010037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
123110037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
123210037SARM gem5 Developers                                                      UXTX, 0);
123310037SARM gem5 Developers        } else {
123410037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
123510037SARM gem5 Developers                                                   totNumBytes);
123610037SARM gem5 Developers        }
123710037SARM gem5 Developers    }
123810037SARM gem5 Developers
123910037SARM gem5 Developers    for(int i = 0; i < numMarshalMicroops; ++i) {
124010037SARM gem5 Developers        microOps[uopIdx++] = new MicroUnpackNeon64(
124110037SARM gem5 Developers            machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
124210037SARM gem5 Developers            numStructElems, index, i /* step */, replicate);
124310037SARM gem5 Developers    }
124410037SARM gem5 Developers
124510037SARM gem5 Developers    assert(uopIdx == numMicroops);
124610037SARM gem5 Developers
124710037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; i++) {
124810037SARM gem5 Developers        microOps[i]->setDelayedCommit();
124910037SARM gem5 Developers    }
125010037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
125110037SARM gem5 Developers}
125210037SARM gem5 Developers
125310037SARM gem5 DevelopersVstSingleOp64::VstSingleOp64(const char *mnem, ExtMachInst machInst,
125410037SARM gem5 Developers                             OpClass __opClass, RegIndex rn, RegIndex vd,
125510037SARM gem5 Developers                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
125610037SARM gem5 Developers                             uint8_t numStructElems, uint8_t index, bool wb,
125710037SARM gem5 Developers                             bool replicate) :
125810037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
125910037SARM gem5 Developers{
126010037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
126110037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
126210037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
126310037SARM gem5 Developers
126410037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
126510037SARM gem5 Developers
126610037SARM gem5 Developers    int eSizeBytes = 1 << eSize;
126710037SARM gem5 Developers    int totNumBytes = numStructElems * eSizeBytes;
126810037SARM gem5 Developers    assert(totNumBytes <= 64);
126910037SARM gem5 Developers
127010037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
127110037SARM gem5 Developers    // transferred at a time
127210037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
127310037SARM gem5 Developers    int residuum = totNumBytes % 16;
127410037SARM gem5 Developers    if (residuum)
127510037SARM gem5 Developers        ++numMemMicroops;
127610037SARM gem5 Developers    numMicroops += numMemMicroops;
127710037SARM gem5 Developers
127810037SARM gem5 Developers    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
127910037SARM gem5 Developers    numMicroops += numMarshalMicroops;
128010037SARM gem5 Developers
128110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
128210037SARM gem5 Developers    unsigned uopIdx = 0;
128310037SARM gem5 Developers
128410037SARM gem5 Developers    for(int i = 0; i < numMarshalMicroops; ++i) {
128510037SARM gem5 Developers        microOps[uopIdx++] = new MicroPackNeon64(
128610037SARM gem5 Developers            machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
128710037SARM gem5 Developers            numStructElems, index, i /* step */, replicate);
128810037SARM gem5 Developers    }
128910037SARM gem5 Developers
129010037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
129110037SARM gem5 Developers        TLB::AllowUnaligned;
129210037SARM gem5 Developers
129310037SARM gem5 Developers    int i = 0;
129410037SARM gem5 Developers    for(; i < numMemMicroops - 1; ++i) {
129510037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonStore64(
129610037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
129710037SARM gem5 Developers            baseIsSP, 16 /* accsize */, eSize);
129810037SARM gem5 Developers    }
129910037SARM gem5 Developers    microOps[uopIdx++] = new MicroNeonStore64(
130010037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
130110037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
130210037SARM gem5 Developers
130310037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
130410037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
130510037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
130610037SARM gem5 Developers    if (wb) {
130710037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
130810037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
130910037SARM gem5 Developers                                                      UXTX, 0);
131010037SARM gem5 Developers        } else {
131110037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
131210037SARM gem5 Developers                                                   totNumBytes);
131310037SARM gem5 Developers        }
131410037SARM gem5 Developers    }
131510037SARM gem5 Developers
131610037SARM gem5 Developers    assert(uopIdx == numMicroops);
131710037SARM gem5 Developers
131810037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; i++) {
131910037SARM gem5 Developers        microOps[i]->setDelayedCommit();
132010037SARM gem5 Developers    }
132110037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
132210037SARM gem5 Developers}
132310037SARM gem5 Developers
13247175Sgblack@eecs.umich.eduMacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
13257175Sgblack@eecs.umich.edu                             OpClass __opClass, IntRegIndex rn,
13267175Sgblack@eecs.umich.edu                             RegIndex vd, bool single, bool up,
13277175Sgblack@eecs.umich.edu                             bool writeback, bool load, uint32_t offset) :
13287175Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
13297175Sgblack@eecs.umich.edu{
13307175Sgblack@eecs.umich.edu    int i = 0;
13317175Sgblack@eecs.umich.edu
13327175Sgblack@eecs.umich.edu    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
13337175Sgblack@eecs.umich.edu    // to be functionally identical except that fldmx is deprecated. For now
13347175Sgblack@eecs.umich.edu    // we'll assume they're otherwise interchangable.
13357175Sgblack@eecs.umich.edu    int count = (single ? offset : (offset / 2));
133610037SARM gem5 Developers    if (count == 0 || count > NumFloatV7ArchRegs)
13377175Sgblack@eecs.umich.edu        warn_once("Bad offset field for VFP load/store multiple.\n");
13387175Sgblack@eecs.umich.edu    if (count == 0) {
13397175Sgblack@eecs.umich.edu        // Force there to be at least one microop so the macroop makes sense.
13407175Sgblack@eecs.umich.edu        writeback = true;
13417175Sgblack@eecs.umich.edu    }
134210037SARM gem5 Developers    if (count > NumFloatV7ArchRegs)
134310037SARM gem5 Developers        count = NumFloatV7ArchRegs;
13447175Sgblack@eecs.umich.edu
13457342Sgblack@eecs.umich.edu    numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
13467342Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
13477342Sgblack@eecs.umich.edu
13487395Sgblack@eecs.umich.edu    int64_t addr = 0;
13497175Sgblack@eecs.umich.edu
13507342Sgblack@eecs.umich.edu    if (!up)
13517342Sgblack@eecs.umich.edu        addr = 4 * offset;
13527175Sgblack@eecs.umich.edu
13537342Sgblack@eecs.umich.edu    bool tempUp = up;
13547175Sgblack@eecs.umich.edu    for (int j = 0; j < count; j++) {
13557175Sgblack@eecs.umich.edu        if (load) {
13567639Sgblack@eecs.umich.edu            if (single) {
13577639Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
13587639Sgblack@eecs.umich.edu                                                  tempUp, addr);
13597639Sgblack@eecs.umich.edu            } else {
13607639Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn,
13617639Sgblack@eecs.umich.edu                                                    tempUp, addr);
13627639Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp,
13637639Sgblack@eecs.umich.edu                                                    addr + (up ? 4 : -4));
13647639Sgblack@eecs.umich.edu            }
13657175Sgblack@eecs.umich.edu        } else {
13667639Sgblack@eecs.umich.edu            if (single) {
13677639Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
13687639Sgblack@eecs.umich.edu                                                  tempUp, addr);
13697639Sgblack@eecs.umich.edu            } else {
13707639Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn,
13717639Sgblack@eecs.umich.edu                                                    tempUp, addr);
13727639Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp,
13737639Sgblack@eecs.umich.edu                                                    addr + (up ? 4 : -4));
13747639Sgblack@eecs.umich.edu            }
13757175Sgblack@eecs.umich.edu        }
13767342Sgblack@eecs.umich.edu        if (!tempUp) {
13777342Sgblack@eecs.umich.edu            addr -= (single ? 4 : 8);
13787342Sgblack@eecs.umich.edu            // The microops don't handle negative displacement, so turn if we
13797342Sgblack@eecs.umich.edu            // hit zero, flip polarity and start adding.
13807395Sgblack@eecs.umich.edu            if (addr <= 0) {
13817342Sgblack@eecs.umich.edu                tempUp = true;
13827395Sgblack@eecs.umich.edu                addr = -addr;
13837342Sgblack@eecs.umich.edu            }
13847342Sgblack@eecs.umich.edu        } else {
13857342Sgblack@eecs.umich.edu            addr += (single ? 4 : 8);
13867342Sgblack@eecs.umich.edu        }
13877175Sgblack@eecs.umich.edu    }
13887175Sgblack@eecs.umich.edu
13897175Sgblack@eecs.umich.edu    if (writeback) {
13907175Sgblack@eecs.umich.edu        if (up) {
13917175Sgblack@eecs.umich.edu            microOps[i++] =
13927175Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, 4 * offset);
13937175Sgblack@eecs.umich.edu        } else {
13947175Sgblack@eecs.umich.edu            microOps[i++] =
13957175Sgblack@eecs.umich.edu                new MicroSubiUop(machInst, rn, rn, 4 * offset);
13967175Sgblack@eecs.umich.edu        }
13977175Sgblack@eecs.umich.edu    }
13987175Sgblack@eecs.umich.edu
13997342Sgblack@eecs.umich.edu    assert(numMicroops == i);
14007175Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
14017343Sgblack@eecs.umich.edu
14027343Sgblack@eecs.umich.edu    for (StaticInstPtr *curUop = microOps;
14037343Sgblack@eecs.umich.edu            !(*curUop)->isLastMicroop(); curUop++) {
14047343Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
14057343Sgblack@eecs.umich.edu        assert(uopPtr);
14067343Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
14077343Sgblack@eecs.umich.edu    }
14087170Sgblack@eecs.umich.edu}
14097175Sgblack@eecs.umich.edu
14107615Sminkyu.jeong@arm.comstd::string
14117639Sgblack@eecs.umich.eduMicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14127639Sgblack@eecs.umich.edu{
14137639Sgblack@eecs.umich.edu    std::stringstream ss;
14147639Sgblack@eecs.umich.edu    printMnemonic(ss);
14157639Sgblack@eecs.umich.edu    printReg(ss, ura);
14167639Sgblack@eecs.umich.edu    ss << ", ";
14177639Sgblack@eecs.umich.edu    printReg(ss, urb);
14187639Sgblack@eecs.umich.edu    ss << ", ";
14197639Sgblack@eecs.umich.edu    ccprintf(ss, "#%d", imm);
14207639Sgblack@eecs.umich.edu    return ss.str();
14217639Sgblack@eecs.umich.edu}
14227639Sgblack@eecs.umich.edu
14237639Sgblack@eecs.umich.edustd::string
142410037SARM gem5 DevelopersMicroIntImmXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
142510037SARM gem5 Developers{
142610037SARM gem5 Developers    std::stringstream ss;
142710037SARM gem5 Developers    printMnemonic(ss);
142810037SARM gem5 Developers    printReg(ss, ura);
142910037SARM gem5 Developers    ss << ", ";
143010037SARM gem5 Developers    printReg(ss, urb);
143110037SARM gem5 Developers    ss << ", ";
143210037SARM gem5 Developers    ccprintf(ss, "#%d", imm);
143310037SARM gem5 Developers    return ss.str();
143410037SARM gem5 Developers}
143510037SARM gem5 Developers
143610037SARM gem5 Developersstd::string
14378140SMatt.Horsnell@arm.comMicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14388140SMatt.Horsnell@arm.com{
14398140SMatt.Horsnell@arm.com    std::stringstream ss;
14408140SMatt.Horsnell@arm.com    printMnemonic(ss);
14418140SMatt.Horsnell@arm.com    ss << "[PC,CPSR]";
14428140SMatt.Horsnell@arm.com    return ss.str();
14438140SMatt.Horsnell@arm.com}
14448140SMatt.Horsnell@arm.com
14458140SMatt.Horsnell@arm.comstd::string
144610037SARM gem5 DevelopersMicroIntRegXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
144710037SARM gem5 Developers{
144810037SARM gem5 Developers    std::stringstream ss;
144910037SARM gem5 Developers    printMnemonic(ss);
145010037SARM gem5 Developers    printReg(ss, ura);
145110037SARM gem5 Developers    ccprintf(ss, ", ");
145210037SARM gem5 Developers    printReg(ss, urb);
145310037SARM gem5 Developers    printExtendOperand(false, ss, (IntRegIndex)urc, type, shiftAmt);
145410037SARM gem5 Developers    return ss.str();
145510037SARM gem5 Developers}
145610037SARM gem5 Developers
145710037SARM gem5 Developersstd::string
14587646Sgene.wu@arm.comMicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14597646Sgene.wu@arm.com{
14607646Sgene.wu@arm.com    std::stringstream ss;
14617646Sgene.wu@arm.com    printMnemonic(ss);
14627646Sgene.wu@arm.com    printReg(ss, ura);
14637646Sgene.wu@arm.com    ss << ", ";
14647646Sgene.wu@arm.com    printReg(ss, urb);
14657646Sgene.wu@arm.com    return ss.str();
14667646Sgene.wu@arm.com}
14677646Sgene.wu@arm.com
14687646Sgene.wu@arm.comstd::string
14697615Sminkyu.jeong@arm.comMicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14707615Sminkyu.jeong@arm.com{
14717615Sminkyu.jeong@arm.com    std::stringstream ss;
14727615Sminkyu.jeong@arm.com    printMnemonic(ss);
14737615Sminkyu.jeong@arm.com    printReg(ss, ura);
14747615Sminkyu.jeong@arm.com    ss << ", ";
14757615Sminkyu.jeong@arm.com    printReg(ss, urb);
14767615Sminkyu.jeong@arm.com    ss << ", ";
14777639Sgblack@eecs.umich.edu    printReg(ss, urc);
14787615Sminkyu.jeong@arm.com    return ss.str();
14797175Sgblack@eecs.umich.edu}
14807615Sminkyu.jeong@arm.com
14817615Sminkyu.jeong@arm.comstd::string
14827615Sminkyu.jeong@arm.comMicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14837615Sminkyu.jeong@arm.com{
14847615Sminkyu.jeong@arm.com    std::stringstream ss;
14857615Sminkyu.jeong@arm.com    printMnemonic(ss);
14867615Sminkyu.jeong@arm.com    printReg(ss, ura);
14877615Sminkyu.jeong@arm.com    ss << ", [";
14887615Sminkyu.jeong@arm.com    printReg(ss, urb);
14897615Sminkyu.jeong@arm.com    ss << ", ";
14907615Sminkyu.jeong@arm.com    ccprintf(ss, "#%d", imm);
14917615Sminkyu.jeong@arm.com    ss << "]";
14927615Sminkyu.jeong@arm.com    return ss.str();
14937615Sminkyu.jeong@arm.com}
14947615Sminkyu.jeong@arm.com
14957615Sminkyu.jeong@arm.com}
1496