macromem.cc revision 10339
17170Sgblack@eecs.umich.edu/*
210339Smitch.hayenga@arm.com * Copyright (c) 2010-2014 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
17410199SAndrew.Bardsley@arm.com    /* Take the control flags from the last microop for the macroop */
17510199SAndrew.Bardsley@arm.com    if ((*uop)->isControl())
17610199SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsControl);
17710199SAndrew.Bardsley@arm.com    if ((*uop)->isCondCtrl())
17810199SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsCondControl);
17910199SAndrew.Bardsley@arm.com    if ((*uop)->isIndirectCtrl())
18010199SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsIndirectControl);
18110199SAndrew.Bardsley@arm.com    if ((*uop)->isReturn())
18210199SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsReturn);
18310199SAndrew.Bardsley@arm.com
1847343Sgblack@eecs.umich.edu    for (StaticInstPtr *curUop = microOps;
1857343Sgblack@eecs.umich.edu            !(*curUop)->isLastMicroop(); curUop++) {
1867343Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
1877343Sgblack@eecs.umich.edu        assert(uopPtr);
1887343Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
1897343Sgblack@eecs.umich.edu    }
1907170Sgblack@eecs.umich.edu}
1917170Sgblack@eecs.umich.edu
19210037SARM gem5 DevelopersPairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
19310037SARM gem5 Developers                     uint32_t size, bool fp, bool load, bool noAlloc,
19410037SARM gem5 Developers                     bool signExt, bool exclusive, bool acrel,
19510037SARM gem5 Developers                     int64_t imm, AddrMode mode,
19610037SARM gem5 Developers                     IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) :
19710037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
19810037SARM gem5 Developers{
19910037SARM gem5 Developers    bool writeback = (mode != AddrMd_Offset);
20010037SARM gem5 Developers    numMicroops = 1 + (size / 4) + (writeback ? 1 : 0);
20110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
20210037SARM gem5 Developers
20310037SARM gem5 Developers    StaticInstPtr *uop = microOps;
20410037SARM gem5 Developers
20510037SARM gem5 Developers    bool post = (mode == AddrMd_PostIndex);
20610037SARM gem5 Developers
20710037SARM gem5 Developers    rn = makeSP(rn);
20810037SARM gem5 Developers
20910037SARM gem5 Developers    *uop = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, post ? 0 : imm);
21010037SARM gem5 Developers
21110037SARM gem5 Developers    if (fp) {
21210037SARM gem5 Developers        if (size == 16) {
21310037SARM gem5 Developers            if (load) {
21410037SARM gem5 Developers                *++uop = new MicroLdrQBFpXImmUop(machInst, rt,
21510037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21610037SARM gem5 Developers                *++uop = new MicroLdrQTFpXImmUop(machInst, rt,
21710037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21810037SARM gem5 Developers                *++uop = new MicroLdrQBFpXImmUop(machInst, rt2,
21910037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22010037SARM gem5 Developers                *++uop = new MicroLdrQTFpXImmUop(machInst, rt2,
22110037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22210037SARM gem5 Developers            } else {
22310037SARM gem5 Developers                *++uop = new MicroStrQBFpXImmUop(machInst, rt,
22410037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
22510037SARM gem5 Developers                *++uop = new MicroStrQTFpXImmUop(machInst, rt,
22610037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
22710037SARM gem5 Developers                *++uop = new MicroStrQBFpXImmUop(machInst, rt2,
22810037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22910037SARM gem5 Developers                *++uop = new MicroStrQTFpXImmUop(machInst, rt2,
23010037SARM gem5 Developers                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
23110037SARM gem5 Developers            }
23210037SARM gem5 Developers        } else if (size == 8) {
23310037SARM gem5 Developers            if (load) {
23410037SARM gem5 Developers                *++uop = new MicroLdrFpXImmUop(machInst, rt,
23510037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
23610037SARM gem5 Developers                *++uop = new MicroLdrFpXImmUop(machInst, rt2,
23710037SARM gem5 Developers                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
23810037SARM gem5 Developers            } else {
23910037SARM gem5 Developers                *++uop = new MicroStrFpXImmUop(machInst, rt,
24010037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
24110037SARM gem5 Developers                *++uop = new MicroStrFpXImmUop(machInst, rt2,
24210037SARM gem5 Developers                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
24310037SARM gem5 Developers            }
24410037SARM gem5 Developers        } else if (size == 4) {
24510037SARM gem5 Developers            if (load) {
24610037SARM gem5 Developers                *++uop = new MicroLdrDFpXImmUop(machInst, rt, rt2,
24710037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
24810037SARM gem5 Developers            } else {
24910037SARM gem5 Developers                *++uop = new MicroStrDFpXImmUop(machInst, rt, rt2,
25010037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
25110037SARM gem5 Developers            }
25210037SARM gem5 Developers        }
25310037SARM gem5 Developers    } else {
25410037SARM gem5 Developers        if (size == 8) {
25510037SARM gem5 Developers            if (load) {
25610037SARM gem5 Developers                *++uop = new MicroLdrXImmUop(machInst, rt, INTREG_UREG0,
25710037SARM gem5 Developers                        0, noAlloc, exclusive, acrel);
25810037SARM gem5 Developers                *++uop = new MicroLdrXImmUop(machInst, rt2, INTREG_UREG0,
25910037SARM gem5 Developers                        size, noAlloc, exclusive, acrel);
26010037SARM gem5 Developers            } else {
26110037SARM gem5 Developers                *++uop = new MicroStrXImmUop(machInst, rt, INTREG_UREG0,
26210037SARM gem5 Developers                        0, noAlloc, exclusive, acrel);
26310037SARM gem5 Developers                *++uop = new MicroStrXImmUop(machInst, rt2, INTREG_UREG0,
26410037SARM gem5 Developers                        size, noAlloc, exclusive, acrel);
26510037SARM gem5 Developers            }
26610037SARM gem5 Developers        } else if (size == 4) {
26710037SARM gem5 Developers            if (load) {
26810037SARM gem5 Developers                if (signExt) {
26910037SARM gem5 Developers                    *++uop = new MicroLdrDSXImmUop(machInst, rt, rt2,
27010037SARM gem5 Developers                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27110037SARM gem5 Developers                } else {
27210037SARM gem5 Developers                    *++uop = new MicroLdrDUXImmUop(machInst, rt, rt2,
27310037SARM gem5 Developers                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27410037SARM gem5 Developers                }
27510037SARM gem5 Developers            } else {
27610037SARM gem5 Developers                *++uop = new MicroStrDXImmUop(machInst, rt, rt2,
27710037SARM gem5 Developers                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27810037SARM gem5 Developers            }
27910037SARM gem5 Developers        }
28010037SARM gem5 Developers    }
28110037SARM gem5 Developers
28210037SARM gem5 Developers    if (writeback) {
28310037SARM gem5 Developers        *++uop = new MicroAddXiUop(machInst, rn, INTREG_UREG0,
28410037SARM gem5 Developers                                   post ? imm : 0);
28510037SARM gem5 Developers    }
28610037SARM gem5 Developers
28710037SARM gem5 Developers    (*uop)->setLastMicroop();
28810037SARM gem5 Developers
28910037SARM gem5 Developers    for (StaticInstPtr *curUop = microOps;
29010037SARM gem5 Developers            !(*curUop)->isLastMicroop(); curUop++) {
29110037SARM gem5 Developers        (*curUop)->setDelayedCommit();
29210037SARM gem5 Developers    }
29310037SARM gem5 Developers}
29410037SARM gem5 Developers
29510037SARM gem5 DevelopersBigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst,
29610037SARM gem5 Developers                             OpClass __opClass, bool load, IntRegIndex dest,
29710037SARM gem5 Developers                             IntRegIndex base, int64_t imm) :
29810037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
29910037SARM gem5 Developers{
30010037SARM gem5 Developers    numMicroops = 2;
30110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
30210037SARM gem5 Developers
30310037SARM gem5 Developers    if (load) {
30410037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
30510037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
30610037SARM gem5 Developers    } else {
30710037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
30810037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
30910037SARM gem5 Developers    }
31010037SARM gem5 Developers    microOps[0]->setDelayedCommit();
31110037SARM gem5 Developers    microOps[1]->setLastMicroop();
31210037SARM gem5 Developers}
31310037SARM gem5 Developers
31410037SARM gem5 DevelopersBigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst,
31510037SARM gem5 Developers                               OpClass __opClass, bool load, IntRegIndex dest,
31610037SARM gem5 Developers                               IntRegIndex base, int64_t imm) :
31710037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
31810037SARM gem5 Developers{
31910037SARM gem5 Developers    numMicroops = 3;
32010037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
32110037SARM gem5 Developers
32210037SARM gem5 Developers    if (load) {
32310037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, 0);
32410037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, 0);
32510037SARM gem5 Developers    } else {
32610037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, 0);
32710037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, 0);
32810037SARM gem5 Developers    }
32910037SARM gem5 Developers    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
33010037SARM gem5 Developers
33110037SARM gem5 Developers    microOps[0]->setDelayedCommit();
33210037SARM gem5 Developers    microOps[1]->setDelayedCommit();
33310037SARM gem5 Developers    microOps[2]->setLastMicroop();
33410037SARM gem5 Developers}
33510037SARM gem5 Developers
33610037SARM gem5 DevelopersBigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst,
33710037SARM gem5 Developers                             OpClass __opClass, bool load, IntRegIndex dest,
33810037SARM gem5 Developers                             IntRegIndex base, int64_t imm) :
33910037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
34010037SARM gem5 Developers{
34110037SARM gem5 Developers    numMicroops = 3;
34210037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
34310037SARM gem5 Developers
34410037SARM gem5 Developers    if (load) {
34510037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
34610037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
34710037SARM gem5 Developers    } else {
34810037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
34910037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
35010037SARM gem5 Developers    }
35110037SARM gem5 Developers    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
35210037SARM gem5 Developers
35310037SARM gem5 Developers    microOps[0]->setDelayedCommit();
35410037SARM gem5 Developers    microOps[1]->setDelayedCommit();
35510037SARM gem5 Developers    microOps[2]->setLastMicroop();
35610037SARM gem5 Developers}
35710037SARM gem5 Developers
35810037SARM gem5 DevelopersBigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst,
35910037SARM gem5 Developers                             OpClass __opClass, bool load, IntRegIndex dest,
36010037SARM gem5 Developers                             IntRegIndex base, IntRegIndex offset,
36110037SARM gem5 Developers                             ArmExtendType type, int64_t imm) :
36210037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
36310037SARM gem5 Developers{
36410037SARM gem5 Developers    numMicroops = 2;
36510037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
36610037SARM gem5 Developers
36710037SARM gem5 Developers    if (load) {
36810037SARM gem5 Developers        microOps[0] = new MicroLdrQBFpXRegUop(machInst, dest, base,
36910037SARM gem5 Developers                                              offset, type, imm);
37010037SARM gem5 Developers        microOps[1] = new MicroLdrQTFpXRegUop(machInst, dest, base,
37110037SARM gem5 Developers                                              offset, type, imm);
37210037SARM gem5 Developers    } else {
37310037SARM gem5 Developers        microOps[0] = new MicroStrQBFpXRegUop(machInst, dest, base,
37410037SARM gem5 Developers                                              offset, type, imm);
37510037SARM gem5 Developers        microOps[1] = new MicroStrQTFpXRegUop(machInst, dest, base,
37610037SARM gem5 Developers                                              offset, type, imm);
37710037SARM gem5 Developers    }
37810037SARM gem5 Developers
37910037SARM gem5 Developers    microOps[0]->setDelayedCommit();
38010037SARM gem5 Developers    microOps[1]->setLastMicroop();
38110037SARM gem5 Developers}
38210037SARM gem5 Developers
38310037SARM gem5 DevelopersBigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst,
38410037SARM gem5 Developers                             OpClass __opClass, IntRegIndex dest,
38510037SARM gem5 Developers                             int64_t imm) :
38610037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
38710037SARM gem5 Developers{
38810037SARM gem5 Developers    numMicroops = 2;
38910037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
39010037SARM gem5 Developers
39110037SARM gem5 Developers    microOps[0] = new MicroLdrQBFpXLitUop(machInst, dest, imm);
39210037SARM gem5 Developers    microOps[1] = new MicroLdrQTFpXLitUop(machInst, dest, imm);
39310037SARM gem5 Developers
39410037SARM gem5 Developers    microOps[0]->setDelayedCommit();
39510037SARM gem5 Developers    microOps[1]->setLastMicroop();
39610037SARM gem5 Developers}
39710037SARM gem5 Developers
3987639Sgblack@eecs.umich.eduVldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
3997639Sgblack@eecs.umich.edu                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
4007639Sgblack@eecs.umich.edu                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
4017639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
4027639Sgblack@eecs.umich.edu{
4037639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
4047639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
4057639Sgblack@eecs.umich.edu
4067639Sgblack@eecs.umich.edu    numMicroops = (regs > 2) ? 2 : 1;
4077639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
4087639Sgblack@eecs.umich.edu    bool deinterleave = (elems > 1);
4097639Sgblack@eecs.umich.edu
4107639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
4117639Sgblack@eecs.umich.edu    if (deinterleave) numMicroops += (regs / elems);
4127639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
4137639Sgblack@eecs.umich.edu
41410037SARM gem5 Developers    RegIndex rMid = deinterleave ? NumFloatV7ArchRegs : vd * 2;
4157639Sgblack@eecs.umich.edu
4167639Sgblack@eecs.umich.edu    uint32_t noAlign = TLB::MustBeOne;
4177639Sgblack@eecs.umich.edu
4187639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
4197639Sgblack@eecs.umich.edu    switch (regs) {
4207639Sgblack@eecs.umich.edu      case 4:
4217639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4227639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4237639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4247639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
4257639Sgblack@eecs.umich.edu        break;
4267639Sgblack@eecs.umich.edu      case 3:
4277639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4287639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4297639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
4307639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
4317639Sgblack@eecs.umich.edu        break;
4327639Sgblack@eecs.umich.edu      case 2:
4337639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
4347639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4357639Sgblack@eecs.umich.edu        break;
4367639Sgblack@eecs.umich.edu      case 1:
4377639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
4387639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
4397639Sgblack@eecs.umich.edu        break;
4407639Sgblack@eecs.umich.edu      default:
4417853SMatt.Horsnell@ARM.com        // Unknown number of registers
4427853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
4437639Sgblack@eecs.umich.edu    }
4447639Sgblack@eecs.umich.edu    if (wb) {
4457639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
4467639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
4477646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
4487639Sgblack@eecs.umich.edu        } else {
4497639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
4507639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, regs * 8);
4517639Sgblack@eecs.umich.edu        }
4527639Sgblack@eecs.umich.edu    }
4537639Sgblack@eecs.umich.edu    if (deinterleave) {
4547639Sgblack@eecs.umich.edu        switch (elems) {
4557639Sgblack@eecs.umich.edu          case 4:
4567639Sgblack@eecs.umich.edu            assert(regs == 4);
4577639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>(
4587639Sgblack@eecs.umich.edu                    size, machInst, vd * 2, rMid, inc * 2);
4597639Sgblack@eecs.umich.edu            break;
4607639Sgblack@eecs.umich.edu          case 3:
4617639Sgblack@eecs.umich.edu            assert(regs == 3);
4627639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>(
4637639Sgblack@eecs.umich.edu                    size, machInst, vd * 2, rMid, inc * 2);
4647639Sgblack@eecs.umich.edu            break;
4657639Sgblack@eecs.umich.edu          case 2:
4667639Sgblack@eecs.umich.edu            assert(regs == 4 || regs == 2);
4677639Sgblack@eecs.umich.edu            if (regs == 4) {
4687639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4697639Sgblack@eecs.umich.edu                        size, machInst, vd * 2, rMid, inc * 2);
4707639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4717639Sgblack@eecs.umich.edu                        size, machInst, vd * 2 + 2, rMid + 4, inc * 2);
4727639Sgblack@eecs.umich.edu            } else {
4737639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
4747639Sgblack@eecs.umich.edu                        size, machInst, vd * 2, rMid, inc * 2);
4757639Sgblack@eecs.umich.edu            }
4767639Sgblack@eecs.umich.edu            break;
4777639Sgblack@eecs.umich.edu          default:
4787853SMatt.Horsnell@ARM.com            // Bad number of elements to deinterleave
4797853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
4807639Sgblack@eecs.umich.edu        }
4817639Sgblack@eecs.umich.edu    }
4827639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
4837639Sgblack@eecs.umich.edu
4847639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
4857639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
4867639Sgblack@eecs.umich.edu        assert(uopPtr);
4877639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
4887639Sgblack@eecs.umich.edu    }
4897639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
4907639Sgblack@eecs.umich.edu}
4917639Sgblack@eecs.umich.edu
4927639Sgblack@eecs.umich.eduVldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
4937639Sgblack@eecs.umich.edu                         OpClass __opClass, bool all, unsigned elems,
4947639Sgblack@eecs.umich.edu                         RegIndex rn, RegIndex vd, unsigned regs,
4957639Sgblack@eecs.umich.edu                         unsigned inc, uint32_t size, uint32_t align,
4967639Sgblack@eecs.umich.edu                         RegIndex rm, unsigned lane) :
4977639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
4987639Sgblack@eecs.umich.edu{
4997639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
5007639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
5017639Sgblack@eecs.umich.edu
5027639Sgblack@eecs.umich.edu    unsigned eBytes = (1 << size);
5037639Sgblack@eecs.umich.edu    unsigned loadSize = eBytes * elems;
5047639Sgblack@eecs.umich.edu    unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) /
5057639Sgblack@eecs.umich.edu                        sizeof(FloatRegBits);
5067639Sgblack@eecs.umich.edu
5077639Sgblack@eecs.umich.edu    assert(loadRegs > 0 && loadRegs <= 4);
5087639Sgblack@eecs.umich.edu
5097639Sgblack@eecs.umich.edu    numMicroops = 1;
5107639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
5117639Sgblack@eecs.umich.edu
5127639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
5137639Sgblack@eecs.umich.edu    numMicroops += (regs / elems);
5147639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
5157639Sgblack@eecs.umich.edu
51610037SARM gem5 Developers    RegIndex ufp0 = NumFloatV7ArchRegs;
5177639Sgblack@eecs.umich.edu
5187639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
5197639Sgblack@eecs.umich.edu    switch (loadSize) {
5207639Sgblack@eecs.umich.edu      case 1:
5217639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>(
5227639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5237639Sgblack@eecs.umich.edu        break;
5247639Sgblack@eecs.umich.edu      case 2:
5257639Sgblack@eecs.umich.edu        if (eBytes == 2) {
5267639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>(
5277639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5287639Sgblack@eecs.umich.edu        } else {
5297639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>(
5307639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5317639Sgblack@eecs.umich.edu        }
5327639Sgblack@eecs.umich.edu        break;
5337639Sgblack@eecs.umich.edu      case 3:
5347639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_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        switch (eBytes) {
5397639Sgblack@eecs.umich.edu          case 1:
5407639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>(
5417639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5427639Sgblack@eecs.umich.edu            break;
5437639Sgblack@eecs.umich.edu          case 2:
5447639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>(
5457639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5467639Sgblack@eecs.umich.edu            break;
5477639Sgblack@eecs.umich.edu          case 4:
5487639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>(
5497639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5507639Sgblack@eecs.umich.edu            break;
5517639Sgblack@eecs.umich.edu        }
5527639Sgblack@eecs.umich.edu        break;
5537639Sgblack@eecs.umich.edu      case 6:
5547639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>(
5557639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5567639Sgblack@eecs.umich.edu        break;
5577639Sgblack@eecs.umich.edu      case 8:
5587639Sgblack@eecs.umich.edu        switch (eBytes) {
5597639Sgblack@eecs.umich.edu          case 2:
5607639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>(
5617639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5627639Sgblack@eecs.umich.edu            break;
5637639Sgblack@eecs.umich.edu          case 4:
5647639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>(
5657639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
5667639Sgblack@eecs.umich.edu            break;
5677639Sgblack@eecs.umich.edu        }
5687639Sgblack@eecs.umich.edu        break;
5697639Sgblack@eecs.umich.edu      case 12:
5707639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>(
5717639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5727639Sgblack@eecs.umich.edu        break;
5737639Sgblack@eecs.umich.edu      case 16:
5747639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>(
5757639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
5767639Sgblack@eecs.umich.edu        break;
5777639Sgblack@eecs.umich.edu      default:
5787853SMatt.Horsnell@ARM.com        // Unrecognized load size
5797853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
5807639Sgblack@eecs.umich.edu    }
5817639Sgblack@eecs.umich.edu    if (wb) {
5827639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
5837639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
5847646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
5857639Sgblack@eecs.umich.edu        } else {
5867639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
5877639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, loadSize);
5887639Sgblack@eecs.umich.edu        }
5897639Sgblack@eecs.umich.edu    }
5907639Sgblack@eecs.umich.edu    switch (elems) {
5917639Sgblack@eecs.umich.edu      case 4:
5927639Sgblack@eecs.umich.edu        assert(regs == 4);
5937639Sgblack@eecs.umich.edu        switch (size) {
5947639Sgblack@eecs.umich.edu          case 0:
5957639Sgblack@eecs.umich.edu            if (all) {
5967639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>(
5977639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
5987639Sgblack@eecs.umich.edu            } else {
5997639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>(
6007639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6017639Sgblack@eecs.umich.edu            }
6027639Sgblack@eecs.umich.edu            break;
6037639Sgblack@eecs.umich.edu          case 1:
6047639Sgblack@eecs.umich.edu            if (all) {
6057639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>(
6067639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6077639Sgblack@eecs.umich.edu            } else {
6087639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>(
6097639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6107639Sgblack@eecs.umich.edu            }
6117639Sgblack@eecs.umich.edu            break;
6127639Sgblack@eecs.umich.edu          case 2:
6137639Sgblack@eecs.umich.edu            if (all) {
6147639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>(
6157639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6167639Sgblack@eecs.umich.edu            } else {
6177639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>(
6187639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6197639Sgblack@eecs.umich.edu            }
6207639Sgblack@eecs.umich.edu            break;
6217639Sgblack@eecs.umich.edu          default:
6227853SMatt.Horsnell@ARM.com            // Bad size
6237853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
6247639Sgblack@eecs.umich.edu            break;
6257639Sgblack@eecs.umich.edu        }
6267639Sgblack@eecs.umich.edu        break;
6277639Sgblack@eecs.umich.edu      case 3:
6287639Sgblack@eecs.umich.edu        assert(regs == 3);
6297639Sgblack@eecs.umich.edu        switch (size) {
6307639Sgblack@eecs.umich.edu          case 0:
6317639Sgblack@eecs.umich.edu            if (all) {
6327639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>(
6337639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6347639Sgblack@eecs.umich.edu            } else {
6357639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>(
6367639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6377639Sgblack@eecs.umich.edu            }
6387639Sgblack@eecs.umich.edu            break;
6397639Sgblack@eecs.umich.edu          case 1:
6407639Sgblack@eecs.umich.edu            if (all) {
6417639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>(
6427639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6437639Sgblack@eecs.umich.edu            } else {
6447639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>(
6457639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6467639Sgblack@eecs.umich.edu            }
6477639Sgblack@eecs.umich.edu            break;
6487639Sgblack@eecs.umich.edu          case 2:
6497639Sgblack@eecs.umich.edu            if (all) {
6507639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>(
6517639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6527639Sgblack@eecs.umich.edu            } else {
6537639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>(
6547639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6557639Sgblack@eecs.umich.edu            }
6567639Sgblack@eecs.umich.edu            break;
6577639Sgblack@eecs.umich.edu          default:
6587853SMatt.Horsnell@ARM.com            // Bad size
6597853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
6607639Sgblack@eecs.umich.edu            break;
6617639Sgblack@eecs.umich.edu        }
6627639Sgblack@eecs.umich.edu        break;
6637639Sgblack@eecs.umich.edu      case 2:
6647639Sgblack@eecs.umich.edu        assert(regs == 2);
6657639Sgblack@eecs.umich.edu        assert(loadRegs <= 2);
6667639Sgblack@eecs.umich.edu        switch (size) {
6677639Sgblack@eecs.umich.edu          case 0:
6687639Sgblack@eecs.umich.edu            if (all) {
6697639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>(
6707639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6717639Sgblack@eecs.umich.edu            } else {
6727639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>(
6737639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6747639Sgblack@eecs.umich.edu            }
6757639Sgblack@eecs.umich.edu            break;
6767639Sgblack@eecs.umich.edu          case 1:
6777639Sgblack@eecs.umich.edu            if (all) {
6787639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>(
6797639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6807639Sgblack@eecs.umich.edu            } else {
6817639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>(
6827639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6837639Sgblack@eecs.umich.edu            }
6847639Sgblack@eecs.umich.edu            break;
6857639Sgblack@eecs.umich.edu          case 2:
6867639Sgblack@eecs.umich.edu            if (all) {
6877639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>(
6887639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2);
6897639Sgblack@eecs.umich.edu            } else {
6907639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>(
6917639Sgblack@eecs.umich.edu                        machInst, vd * 2, ufp0, inc * 2, lane);
6927639Sgblack@eecs.umich.edu            }
6937639Sgblack@eecs.umich.edu            break;
6947639Sgblack@eecs.umich.edu          default:
6957853SMatt.Horsnell@ARM.com            // Bad size
6967853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
6977639Sgblack@eecs.umich.edu            break;
6987639Sgblack@eecs.umich.edu        }
6997639Sgblack@eecs.umich.edu        break;
7007639Sgblack@eecs.umich.edu      case 1:
7017639Sgblack@eecs.umich.edu        assert(regs == 1 || (all && regs == 2));
7027639Sgblack@eecs.umich.edu        assert(loadRegs <= 2);
7037639Sgblack@eecs.umich.edu        for (unsigned offset = 0; offset < regs; offset++) {
7047639Sgblack@eecs.umich.edu            switch (size) {
7057639Sgblack@eecs.umich.edu              case 0:
7067639Sgblack@eecs.umich.edu                if (all) {
7077639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7087639Sgblack@eecs.umich.edu                        new MicroUnpackAllNeon2to2Uop<uint8_t>(
7097639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2);
7107639Sgblack@eecs.umich.edu                } else {
7117639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7127639Sgblack@eecs.umich.edu                        new MicroUnpackNeon2to2Uop<uint8_t>(
7137639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
7147639Sgblack@eecs.umich.edu                }
7157639Sgblack@eecs.umich.edu                break;
7167639Sgblack@eecs.umich.edu              case 1:
7177639Sgblack@eecs.umich.edu                if (all) {
7187639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7197639Sgblack@eecs.umich.edu                        new MicroUnpackAllNeon2to2Uop<uint16_t>(
7207639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2);
7217639Sgblack@eecs.umich.edu                } else {
7227639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7237639Sgblack@eecs.umich.edu                        new MicroUnpackNeon2to2Uop<uint16_t>(
7247639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
7257639Sgblack@eecs.umich.edu                }
7267639Sgblack@eecs.umich.edu                break;
7277639Sgblack@eecs.umich.edu              case 2:
7287639Sgblack@eecs.umich.edu                if (all) {
7297639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7307639Sgblack@eecs.umich.edu                        new MicroUnpackAllNeon2to2Uop<uint32_t>(
7317639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2);
7327639Sgblack@eecs.umich.edu                } else {
7337639Sgblack@eecs.umich.edu                    microOps[uopIdx++] =
7347639Sgblack@eecs.umich.edu                        new MicroUnpackNeon2to2Uop<uint32_t>(
7357639Sgblack@eecs.umich.edu                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
7367639Sgblack@eecs.umich.edu                }
7377639Sgblack@eecs.umich.edu                break;
7387639Sgblack@eecs.umich.edu              default:
7397853SMatt.Horsnell@ARM.com                // Bad size
7407853SMatt.Horsnell@ARM.com                microOps[uopIdx++] = new Unknown(machInst);
7417639Sgblack@eecs.umich.edu                break;
7427639Sgblack@eecs.umich.edu            }
7437639Sgblack@eecs.umich.edu        }
7447639Sgblack@eecs.umich.edu        break;
7457639Sgblack@eecs.umich.edu      default:
7467853SMatt.Horsnell@ARM.com        // Bad number of elements to unpack
7477853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
7487639Sgblack@eecs.umich.edu    }
7497639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
7507639Sgblack@eecs.umich.edu
7517639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
7527639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
7537639Sgblack@eecs.umich.edu        assert(uopPtr);
7547639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
7557639Sgblack@eecs.umich.edu    }
7567639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
7577639Sgblack@eecs.umich.edu}
7587639Sgblack@eecs.umich.edu
7597639Sgblack@eecs.umich.eduVstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
7607639Sgblack@eecs.umich.edu                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
7617639Sgblack@eecs.umich.edu                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
7627639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
7637639Sgblack@eecs.umich.edu{
7647639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
7657639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
7667639Sgblack@eecs.umich.edu
7677639Sgblack@eecs.umich.edu    numMicroops = (regs > 2) ? 2 : 1;
7687639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
7697639Sgblack@eecs.umich.edu    bool interleave = (elems > 1);
7707639Sgblack@eecs.umich.edu
7717639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
7727639Sgblack@eecs.umich.edu    if (interleave) numMicroops += (regs / elems);
7737639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
7747639Sgblack@eecs.umich.edu
7757639Sgblack@eecs.umich.edu    uint32_t noAlign = TLB::MustBeOne;
7767639Sgblack@eecs.umich.edu
77710037SARM gem5 Developers    RegIndex rMid = interleave ? NumFloatV7ArchRegs : vd * 2;
7787639Sgblack@eecs.umich.edu
7797639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
7807639Sgblack@eecs.umich.edu    if (interleave) {
7817639Sgblack@eecs.umich.edu        switch (elems) {
7827639Sgblack@eecs.umich.edu          case 4:
7837639Sgblack@eecs.umich.edu            assert(regs == 4);
7847639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>(
7857639Sgblack@eecs.umich.edu                    size, machInst, rMid, vd * 2, inc * 2);
7867639Sgblack@eecs.umich.edu            break;
7877639Sgblack@eecs.umich.edu          case 3:
7887639Sgblack@eecs.umich.edu            assert(regs == 3);
7897639Sgblack@eecs.umich.edu            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>(
7907639Sgblack@eecs.umich.edu                    size, machInst, rMid, vd * 2, inc * 2);
7917639Sgblack@eecs.umich.edu            break;
7927639Sgblack@eecs.umich.edu          case 2:
7937639Sgblack@eecs.umich.edu            assert(regs == 4 || regs == 2);
7947639Sgblack@eecs.umich.edu            if (regs == 4) {
7957639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
7967639Sgblack@eecs.umich.edu                        size, machInst, rMid, vd * 2, inc * 2);
7977639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
7987639Sgblack@eecs.umich.edu                        size, machInst, rMid + 4, vd * 2 + 2, inc * 2);
7997639Sgblack@eecs.umich.edu            } else {
8007639Sgblack@eecs.umich.edu                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
8017639Sgblack@eecs.umich.edu                        size, machInst, rMid, vd * 2, inc * 2);
8027639Sgblack@eecs.umich.edu            }
8037639Sgblack@eecs.umich.edu            break;
8047639Sgblack@eecs.umich.edu          default:
8057853SMatt.Horsnell@ARM.com            // Bad number of elements to interleave
8067853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
8077639Sgblack@eecs.umich.edu        }
8087639Sgblack@eecs.umich.edu    }
8097639Sgblack@eecs.umich.edu    switch (regs) {
8107639Sgblack@eecs.umich.edu      case 4:
8117639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8127639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8137639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8147639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
8157639Sgblack@eecs.umich.edu        break;
8167639Sgblack@eecs.umich.edu      case 3:
8177639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8187639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8197639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
8207639Sgblack@eecs.umich.edu                size, machInst, rMid + 4, rn, 16, noAlign);
8217639Sgblack@eecs.umich.edu        break;
8227639Sgblack@eecs.umich.edu      case 2:
8237639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
8247639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8257639Sgblack@eecs.umich.edu        break;
8267639Sgblack@eecs.umich.edu      case 1:
8277639Sgblack@eecs.umich.edu        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
8287639Sgblack@eecs.umich.edu                size, machInst, rMid, rn, 0, align);
8297639Sgblack@eecs.umich.edu        break;
8307639Sgblack@eecs.umich.edu      default:
8317853SMatt.Horsnell@ARM.com        // Unknown number of registers
8327853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
8337639Sgblack@eecs.umich.edu    }
8347639Sgblack@eecs.umich.edu    if (wb) {
8357639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
8367639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
8377646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
8387639Sgblack@eecs.umich.edu        } else {
8397639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
8407639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, regs * 8);
8417639Sgblack@eecs.umich.edu        }
8427639Sgblack@eecs.umich.edu    }
8437639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
8447639Sgblack@eecs.umich.edu
8457639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
8467639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
8477639Sgblack@eecs.umich.edu        assert(uopPtr);
8487639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
8497639Sgblack@eecs.umich.edu    }
8507639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
8517639Sgblack@eecs.umich.edu}
8527639Sgblack@eecs.umich.edu
8537639Sgblack@eecs.umich.eduVstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
8547639Sgblack@eecs.umich.edu                         OpClass __opClass, bool all, unsigned elems,
8557639Sgblack@eecs.umich.edu                         RegIndex rn, RegIndex vd, unsigned regs,
8567639Sgblack@eecs.umich.edu                         unsigned inc, uint32_t size, uint32_t align,
8577639Sgblack@eecs.umich.edu                         RegIndex rm, unsigned lane) :
8587639Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
8597639Sgblack@eecs.umich.edu{
8607639Sgblack@eecs.umich.edu    assert(!all);
8617639Sgblack@eecs.umich.edu    assert(regs > 0 && regs <= 4);
8627639Sgblack@eecs.umich.edu    assert(regs % elems == 0);
8637639Sgblack@eecs.umich.edu
8647639Sgblack@eecs.umich.edu    unsigned eBytes = (1 << size);
8657639Sgblack@eecs.umich.edu    unsigned storeSize = eBytes * elems;
8667639Sgblack@eecs.umich.edu    unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) /
8677639Sgblack@eecs.umich.edu                         sizeof(FloatRegBits);
8687639Sgblack@eecs.umich.edu
8697639Sgblack@eecs.umich.edu    assert(storeRegs > 0 && storeRegs <= 4);
8707639Sgblack@eecs.umich.edu
8717639Sgblack@eecs.umich.edu    numMicroops = 1;
8727639Sgblack@eecs.umich.edu    bool wb = (rm != 15);
8737639Sgblack@eecs.umich.edu
8747639Sgblack@eecs.umich.edu    if (wb) numMicroops++;
8757639Sgblack@eecs.umich.edu    numMicroops += (regs / elems);
8767639Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
8777639Sgblack@eecs.umich.edu
87810037SARM gem5 Developers    RegIndex ufp0 = NumFloatV7ArchRegs;
8797639Sgblack@eecs.umich.edu
8807639Sgblack@eecs.umich.edu    unsigned uopIdx = 0;
8817639Sgblack@eecs.umich.edu    switch (elems) {
8827639Sgblack@eecs.umich.edu      case 4:
8837639Sgblack@eecs.umich.edu        assert(regs == 4);
8847639Sgblack@eecs.umich.edu        switch (size) {
8857639Sgblack@eecs.umich.edu          case 0:
8867639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>(
8877639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8887639Sgblack@eecs.umich.edu            break;
8897639Sgblack@eecs.umich.edu          case 1:
8907639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>(
8917639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8927639Sgblack@eecs.umich.edu            break;
8937639Sgblack@eecs.umich.edu          case 2:
8947639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>(
8957639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
8967639Sgblack@eecs.umich.edu            break;
8977639Sgblack@eecs.umich.edu          default:
8987853SMatt.Horsnell@ARM.com            // Bad size
8997853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
9007639Sgblack@eecs.umich.edu            break;
9017639Sgblack@eecs.umich.edu        }
9027639Sgblack@eecs.umich.edu        break;
9037639Sgblack@eecs.umich.edu      case 3:
9047639Sgblack@eecs.umich.edu        assert(regs == 3);
9057639Sgblack@eecs.umich.edu        switch (size) {
9067639Sgblack@eecs.umich.edu          case 0:
9077639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>(
9087639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9097639Sgblack@eecs.umich.edu            break;
9107639Sgblack@eecs.umich.edu          case 1:
9117639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>(
9127639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9137639Sgblack@eecs.umich.edu            break;
9147639Sgblack@eecs.umich.edu          case 2:
9157639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>(
9167639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9177639Sgblack@eecs.umich.edu            break;
9187639Sgblack@eecs.umich.edu          default:
9197853SMatt.Horsnell@ARM.com            // Bad size
9207853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
9217639Sgblack@eecs.umich.edu            break;
9227639Sgblack@eecs.umich.edu        }
9237639Sgblack@eecs.umich.edu        break;
9247639Sgblack@eecs.umich.edu      case 2:
9257639Sgblack@eecs.umich.edu        assert(regs == 2);
9267639Sgblack@eecs.umich.edu        assert(storeRegs <= 2);
9277639Sgblack@eecs.umich.edu        switch (size) {
9287639Sgblack@eecs.umich.edu          case 0:
9297639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>(
9307639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9317639Sgblack@eecs.umich.edu            break;
9327639Sgblack@eecs.umich.edu          case 1:
9337639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>(
9347639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9357639Sgblack@eecs.umich.edu            break;
9367639Sgblack@eecs.umich.edu          case 2:
9377639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>(
9387639Sgblack@eecs.umich.edu                    machInst, ufp0, vd * 2, inc * 2, lane);
9397639Sgblack@eecs.umich.edu            break;
9407639Sgblack@eecs.umich.edu          default:
9417853SMatt.Horsnell@ARM.com            // Bad size
9427853SMatt.Horsnell@ARM.com            microOps[uopIdx++] = new Unknown(machInst);
9437639Sgblack@eecs.umich.edu            break;
9447639Sgblack@eecs.umich.edu        }
9457639Sgblack@eecs.umich.edu        break;
9467639Sgblack@eecs.umich.edu      case 1:
9477639Sgblack@eecs.umich.edu        assert(regs == 1 || (all && regs == 2));
9487639Sgblack@eecs.umich.edu        assert(storeRegs <= 2);
9497639Sgblack@eecs.umich.edu        for (unsigned offset = 0; offset < regs; offset++) {
9507639Sgblack@eecs.umich.edu            switch (size) {
9517639Sgblack@eecs.umich.edu              case 0:
9527639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>(
9537639Sgblack@eecs.umich.edu                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
9547639Sgblack@eecs.umich.edu                break;
9557639Sgblack@eecs.umich.edu              case 1:
9567639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>(
9577639Sgblack@eecs.umich.edu                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
9587639Sgblack@eecs.umich.edu                break;
9597639Sgblack@eecs.umich.edu              case 2:
9607639Sgblack@eecs.umich.edu                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>(
9617639Sgblack@eecs.umich.edu                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
9627639Sgblack@eecs.umich.edu                break;
9637639Sgblack@eecs.umich.edu              default:
9647853SMatt.Horsnell@ARM.com                // Bad size
9657853SMatt.Horsnell@ARM.com                microOps[uopIdx++] = new Unknown(machInst);
9667639Sgblack@eecs.umich.edu                break;
9677639Sgblack@eecs.umich.edu            }
9687639Sgblack@eecs.umich.edu        }
9697639Sgblack@eecs.umich.edu        break;
9707639Sgblack@eecs.umich.edu      default:
9717853SMatt.Horsnell@ARM.com        // Bad number of elements to unpack
9727853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
9737639Sgblack@eecs.umich.edu    }
9747639Sgblack@eecs.umich.edu    switch (storeSize) {
9757639Sgblack@eecs.umich.edu      case 1:
9767639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>(
9777639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
9787639Sgblack@eecs.umich.edu        break;
9797639Sgblack@eecs.umich.edu      case 2:
9807639Sgblack@eecs.umich.edu        if (eBytes == 2) {
9817639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>(
9827639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9837639Sgblack@eecs.umich.edu        } else {
9847639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>(
9857639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9867639Sgblack@eecs.umich.edu        }
9877639Sgblack@eecs.umich.edu        break;
9887639Sgblack@eecs.umich.edu      case 3:
9897639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_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        switch (eBytes) {
9947639Sgblack@eecs.umich.edu          case 1:
9957639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>(
9967639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
9977639Sgblack@eecs.umich.edu            break;
9987639Sgblack@eecs.umich.edu          case 2:
9997639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>(
10007639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10017639Sgblack@eecs.umich.edu            break;
10027639Sgblack@eecs.umich.edu          case 4:
10037639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>(
10047639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10057639Sgblack@eecs.umich.edu            break;
10067639Sgblack@eecs.umich.edu        }
10077639Sgblack@eecs.umich.edu        break;
10087639Sgblack@eecs.umich.edu      case 6:
10097639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>(
10107639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10117639Sgblack@eecs.umich.edu        break;
10127639Sgblack@eecs.umich.edu      case 8:
10137639Sgblack@eecs.umich.edu        switch (eBytes) {
10147639Sgblack@eecs.umich.edu          case 2:
10157639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>(
10167639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10177639Sgblack@eecs.umich.edu            break;
10187639Sgblack@eecs.umich.edu          case 4:
10197639Sgblack@eecs.umich.edu            microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>(
10207639Sgblack@eecs.umich.edu                    machInst, ufp0, rn, 0, align);
10217639Sgblack@eecs.umich.edu            break;
10227639Sgblack@eecs.umich.edu        }
10237639Sgblack@eecs.umich.edu        break;
10247639Sgblack@eecs.umich.edu      case 12:
10257639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>(
10267639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10277639Sgblack@eecs.umich.edu        break;
10287639Sgblack@eecs.umich.edu      case 16:
10297639Sgblack@eecs.umich.edu        microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>(
10307639Sgblack@eecs.umich.edu                machInst, ufp0, rn, 0, align);
10317639Sgblack@eecs.umich.edu        break;
10327639Sgblack@eecs.umich.edu      default:
10337853SMatt.Horsnell@ARM.com        // Bad store size
10347853SMatt.Horsnell@ARM.com        microOps[uopIdx++] = new Unknown(machInst);
10357639Sgblack@eecs.umich.edu    }
10367639Sgblack@eecs.umich.edu    if (wb) {
10377639Sgblack@eecs.umich.edu        if (rm != 15 && rm != 13) {
10387639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
10397646Sgene.wu@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
10407639Sgblack@eecs.umich.edu        } else {
10417639Sgblack@eecs.umich.edu            microOps[uopIdx++] =
10427639Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, storeSize);
10437639Sgblack@eecs.umich.edu        }
10447639Sgblack@eecs.umich.edu    }
10457639Sgblack@eecs.umich.edu    assert(uopIdx == numMicroops);
10467639Sgblack@eecs.umich.edu
10477639Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numMicroops - 1; i++) {
10487639Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
10497639Sgblack@eecs.umich.edu        assert(uopPtr);
10507639Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
10517639Sgblack@eecs.umich.edu    }
10527639Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
10537639Sgblack@eecs.umich.edu}
10547639Sgblack@eecs.umich.edu
105510037SARM gem5 DevelopersVldMultOp64::VldMultOp64(const char *mnem, ExtMachInst machInst,
105610037SARM gem5 Developers                         OpClass __opClass, RegIndex rn, RegIndex vd,
105710037SARM gem5 Developers                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
105810037SARM gem5 Developers                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
105910037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
106010037SARM gem5 Developers{
106110037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
106210037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
106310037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
106410037SARM gem5 Developers
106510037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
106610037SARM gem5 Developers
106710037SARM gem5 Developers    int totNumBytes = numRegs * dataSize / 8;
106810037SARM gem5 Developers    assert(totNumBytes <= 64);
106910037SARM gem5 Developers
107010037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
107110037SARM gem5 Developers    // transferred at a time
107210037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
107310037SARM gem5 Developers    int residuum = totNumBytes % 16;
107410037SARM gem5 Developers    if (residuum)
107510037SARM gem5 Developers        ++numMemMicroops;
107610037SARM gem5 Developers    numMicroops += numMemMicroops;
107710037SARM gem5 Developers
107810037SARM gem5 Developers    int numMarshalMicroops = numRegs / 2 + (numRegs % 2 ? 1 : 0);
107910037SARM gem5 Developers    numMicroops += numMarshalMicroops;
108010037SARM gem5 Developers
108110037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
108210037SARM gem5 Developers    unsigned uopIdx = 0;
108310037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
108410037SARM gem5 Developers        TLB::AllowUnaligned;
108510037SARM gem5 Developers
108610037SARM gem5 Developers    int i = 0;
108710037SARM gem5 Developers    for(; i < numMemMicroops - 1; ++i) {
108810037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonLoad64(
108910037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
109010037SARM gem5 Developers            baseIsSP, 16 /* accSize */, eSize);
109110037SARM gem5 Developers    }
109210037SARM gem5 Developers    microOps[uopIdx++] =  new MicroNeonLoad64(
109310037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
109410037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
109510037SARM gem5 Developers
109610037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
109710037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
109810037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
109910037SARM gem5 Developers    if (wb) {
110010037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
110110037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
110210037SARM gem5 Developers                                                      UXTX, 0);
110310037SARM gem5 Developers        } else {
110410037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
110510037SARM gem5 Developers                                                   totNumBytes);
110610037SARM gem5 Developers        }
110710037SARM gem5 Developers    }
110810037SARM gem5 Developers
110910037SARM gem5 Developers    for (int i = 0; i < numMarshalMicroops; ++i) {
111010339Smitch.hayenga@arm.com        switch(numRegs) {
111110339Smitch.hayenga@arm.com            case 1: microOps[uopIdx++] = new MicroDeintNeon64_1Reg(
111210339Smitch.hayenga@arm.com                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
111310339Smitch.hayenga@arm.com                        numStructElems, 1, i /* step */);
111410339Smitch.hayenga@arm.com                    break;
111510339Smitch.hayenga@arm.com            case 2: microOps[uopIdx++] = new MicroDeintNeon64_2Reg(
111610339Smitch.hayenga@arm.com                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
111710339Smitch.hayenga@arm.com                        numStructElems, 2, i /* step */);
111810339Smitch.hayenga@arm.com                    break;
111910339Smitch.hayenga@arm.com            case 3: microOps[uopIdx++] = new MicroDeintNeon64_3Reg(
112010339Smitch.hayenga@arm.com                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
112110339Smitch.hayenga@arm.com                        numStructElems, 3, i /* step */);
112210339Smitch.hayenga@arm.com                    break;
112310339Smitch.hayenga@arm.com            case 4: microOps[uopIdx++] = new MicroDeintNeon64_4Reg(
112410339Smitch.hayenga@arm.com                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
112510339Smitch.hayenga@arm.com                        numStructElems, 4, i /* step */);
112610339Smitch.hayenga@arm.com                    break;
112710339Smitch.hayenga@arm.com            default: panic("Invalid number of registers");
112810339Smitch.hayenga@arm.com        }
112910339Smitch.hayenga@arm.com
113010037SARM gem5 Developers    }
113110037SARM gem5 Developers
113210037SARM gem5 Developers    assert(uopIdx == numMicroops);
113310037SARM gem5 Developers
113410037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; ++i) {
113510037SARM gem5 Developers        microOps[i]->setDelayedCommit();
113610037SARM gem5 Developers    }
113710037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
113810037SARM gem5 Developers}
113910037SARM gem5 Developers
114010037SARM gem5 DevelopersVstMultOp64::VstMultOp64(const char *mnem, ExtMachInst machInst,
114110037SARM gem5 Developers                         OpClass __opClass, RegIndex rn, RegIndex vd,
114210037SARM gem5 Developers                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
114310037SARM gem5 Developers                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
114410037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
114510037SARM gem5 Developers{
114610037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
114710037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
114810037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
114910037SARM gem5 Developers
115010037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
115110037SARM gem5 Developers
115210037SARM gem5 Developers    int totNumBytes = numRegs * dataSize / 8;
115310037SARM gem5 Developers    assert(totNumBytes <= 64);
115410037SARM gem5 Developers
115510037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
115610037SARM gem5 Developers    // transferred at a time
115710037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
115810037SARM gem5 Developers    int residuum = totNumBytes % 16;
115910037SARM gem5 Developers    if (residuum)
116010037SARM gem5 Developers        ++numMemMicroops;
116110037SARM gem5 Developers    numMicroops += numMemMicroops;
116210037SARM gem5 Developers
116310037SARM gem5 Developers    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
116410037SARM gem5 Developers    numMicroops += numMarshalMicroops;
116510037SARM gem5 Developers
116610037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
116710037SARM gem5 Developers    unsigned uopIdx = 0;
116810037SARM gem5 Developers
116910037SARM gem5 Developers    for(int i = 0; i < numMarshalMicroops; ++i) {
117010339Smitch.hayenga@arm.com        switch (numRegs) {
117110339Smitch.hayenga@arm.com            case 1: microOps[uopIdx++] = new MicroIntNeon64_1Reg(
117210339Smitch.hayenga@arm.com                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
117310339Smitch.hayenga@arm.com                        numStructElems, 1, i /* step */);
117410339Smitch.hayenga@arm.com                    break;
117510339Smitch.hayenga@arm.com            case 2: microOps[uopIdx++] = new MicroIntNeon64_2Reg(
117610339Smitch.hayenga@arm.com                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
117710339Smitch.hayenga@arm.com                        numStructElems, 2, i /* step */);
117810339Smitch.hayenga@arm.com                    break;
117910339Smitch.hayenga@arm.com            case 3: microOps[uopIdx++] = new MicroIntNeon64_3Reg(
118010339Smitch.hayenga@arm.com                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
118110339Smitch.hayenga@arm.com                        numStructElems, 3, i /* step */);
118210339Smitch.hayenga@arm.com                    break;
118310339Smitch.hayenga@arm.com            case 4: microOps[uopIdx++] = new MicroIntNeon64_4Reg(
118410339Smitch.hayenga@arm.com                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
118510339Smitch.hayenga@arm.com                        numStructElems, 4, i /* step */);
118610339Smitch.hayenga@arm.com                    break;
118710339Smitch.hayenga@arm.com            default: panic("Invalid number of registers");
118810339Smitch.hayenga@arm.com        }
118910037SARM gem5 Developers    }
119010037SARM gem5 Developers
119110037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
119210037SARM gem5 Developers        TLB::AllowUnaligned;
119310037SARM gem5 Developers
119410037SARM gem5 Developers    int i = 0;
119510037SARM gem5 Developers    for(; i < numMemMicroops - 1; ++i) {
119610037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonStore64(
119710037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
119810037SARM gem5 Developers            baseIsSP, 16 /* accSize */, eSize);
119910037SARM gem5 Developers    }
120010037SARM gem5 Developers    microOps[uopIdx++] = new MicroNeonStore64(
120110037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
120210037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
120310037SARM gem5 Developers
120410037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
120510037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
120610037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
120710037SARM gem5 Developers    if (wb) {
120810037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
120910037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
121010037SARM gem5 Developers                                                      UXTX, 0);
121110037SARM gem5 Developers        } else {
121210037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
121310037SARM gem5 Developers                                                   totNumBytes);
121410037SARM gem5 Developers        }
121510037SARM gem5 Developers    }
121610037SARM gem5 Developers
121710037SARM gem5 Developers    assert(uopIdx == numMicroops);
121810037SARM gem5 Developers
121910037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; i++) {
122010037SARM gem5 Developers        microOps[i]->setDelayedCommit();
122110037SARM gem5 Developers    }
122210037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
122310037SARM gem5 Developers}
122410037SARM gem5 Developers
122510037SARM gem5 DevelopersVldSingleOp64::VldSingleOp64(const char *mnem, ExtMachInst machInst,
122610037SARM gem5 Developers                             OpClass __opClass, RegIndex rn, RegIndex vd,
122710037SARM gem5 Developers                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
122810037SARM gem5 Developers                             uint8_t numStructElems, uint8_t index, bool wb,
122910037SARM gem5 Developers                             bool replicate) :
123010037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
123110037SARM gem5 Developers{
123210037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
123310037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
123410037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
123510037SARM gem5 Developers
123610037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
123710037SARM gem5 Developers
123810037SARM gem5 Developers    int eSizeBytes = 1 << eSize;
123910037SARM gem5 Developers    int totNumBytes = numStructElems * eSizeBytes;
124010037SARM gem5 Developers    assert(totNumBytes <= 64);
124110037SARM gem5 Developers
124210037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
124310037SARM gem5 Developers    // transferred at a time
124410037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
124510037SARM gem5 Developers    int residuum = totNumBytes % 16;
124610037SARM gem5 Developers    if (residuum)
124710037SARM gem5 Developers        ++numMemMicroops;
124810037SARM gem5 Developers    numMicroops += numMemMicroops;
124910037SARM gem5 Developers
125010037SARM gem5 Developers    int numMarshalMicroops = numStructElems / 2 + (numStructElems % 2 ? 1 : 0);
125110037SARM gem5 Developers    numMicroops += numMarshalMicroops;
125210037SARM gem5 Developers
125310037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
125410037SARM gem5 Developers    unsigned uopIdx = 0;
125510037SARM gem5 Developers
125610037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
125710037SARM gem5 Developers        TLB::AllowUnaligned;
125810037SARM gem5 Developers
125910037SARM gem5 Developers    int i = 0;
126010037SARM gem5 Developers    for (; i < numMemMicroops - 1; ++i) {
126110037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonLoad64(
126210037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
126310037SARM gem5 Developers            baseIsSP, 16 /* accSize */, eSize);
126410037SARM gem5 Developers    }
126510037SARM gem5 Developers    microOps[uopIdx++] = new MicroNeonLoad64(
126610037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
126710037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
126810037SARM gem5 Developers
126910037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
127010037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
127110037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
127210037SARM gem5 Developers    if (wb) {
127310037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
127410037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
127510037SARM gem5 Developers                                                      UXTX, 0);
127610037SARM gem5 Developers        } else {
127710037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
127810037SARM gem5 Developers                                                   totNumBytes);
127910037SARM gem5 Developers        }
128010037SARM gem5 Developers    }
128110037SARM gem5 Developers
128210037SARM gem5 Developers    for(int i = 0; i < numMarshalMicroops; ++i) {
128310037SARM gem5 Developers        microOps[uopIdx++] = new MicroUnpackNeon64(
128410037SARM gem5 Developers            machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
128510037SARM gem5 Developers            numStructElems, index, i /* step */, replicate);
128610037SARM gem5 Developers    }
128710037SARM gem5 Developers
128810037SARM gem5 Developers    assert(uopIdx == numMicroops);
128910037SARM gem5 Developers
129010037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; i++) {
129110037SARM gem5 Developers        microOps[i]->setDelayedCommit();
129210037SARM gem5 Developers    }
129310037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
129410037SARM gem5 Developers}
129510037SARM gem5 Developers
129610037SARM gem5 DevelopersVstSingleOp64::VstSingleOp64(const char *mnem, ExtMachInst machInst,
129710037SARM gem5 Developers                             OpClass __opClass, RegIndex rn, RegIndex vd,
129810037SARM gem5 Developers                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
129910037SARM gem5 Developers                             uint8_t numStructElems, uint8_t index, bool wb,
130010037SARM gem5 Developers                             bool replicate) :
130110037SARM gem5 Developers    PredMacroOp(mnem, machInst, __opClass)
130210037SARM gem5 Developers{
130310037SARM gem5 Developers    RegIndex vx = NumFloatV8ArchRegs / 4;
130410037SARM gem5 Developers    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
130510037SARM gem5 Developers    bool baseIsSP = isSP((IntRegIndex) rnsp);
130610037SARM gem5 Developers
130710037SARM gem5 Developers    numMicroops = wb ? 1 : 0;
130810037SARM gem5 Developers
130910037SARM gem5 Developers    int eSizeBytes = 1 << eSize;
131010037SARM gem5 Developers    int totNumBytes = numStructElems * eSizeBytes;
131110037SARM gem5 Developers    assert(totNumBytes <= 64);
131210037SARM gem5 Developers
131310037SARM gem5 Developers    // The guiding principle here is that no more than 16 bytes can be
131410037SARM gem5 Developers    // transferred at a time
131510037SARM gem5 Developers    int numMemMicroops = totNumBytes / 16;
131610037SARM gem5 Developers    int residuum = totNumBytes % 16;
131710037SARM gem5 Developers    if (residuum)
131810037SARM gem5 Developers        ++numMemMicroops;
131910037SARM gem5 Developers    numMicroops += numMemMicroops;
132010037SARM gem5 Developers
132110037SARM gem5 Developers    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
132210037SARM gem5 Developers    numMicroops += numMarshalMicroops;
132310037SARM gem5 Developers
132410037SARM gem5 Developers    microOps = new StaticInstPtr[numMicroops];
132510037SARM gem5 Developers    unsigned uopIdx = 0;
132610037SARM gem5 Developers
132710037SARM gem5 Developers    for(int i = 0; i < numMarshalMicroops; ++i) {
132810037SARM gem5 Developers        microOps[uopIdx++] = new MicroPackNeon64(
132910037SARM gem5 Developers            machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
133010037SARM gem5 Developers            numStructElems, index, i /* step */, replicate);
133110037SARM gem5 Developers    }
133210037SARM gem5 Developers
133310037SARM gem5 Developers    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
133410037SARM gem5 Developers        TLB::AllowUnaligned;
133510037SARM gem5 Developers
133610037SARM gem5 Developers    int i = 0;
133710037SARM gem5 Developers    for(; i < numMemMicroops - 1; ++i) {
133810037SARM gem5 Developers        microOps[uopIdx++] = new MicroNeonStore64(
133910037SARM gem5 Developers            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
134010037SARM gem5 Developers            baseIsSP, 16 /* accsize */, eSize);
134110037SARM gem5 Developers    }
134210037SARM gem5 Developers    microOps[uopIdx++] = new MicroNeonStore64(
134310037SARM gem5 Developers        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
134410037SARM gem5 Developers        residuum ? residuum : 16 /* accSize */, eSize);
134510037SARM gem5 Developers
134610037SARM gem5 Developers    // Writeback microop: the post-increment amount is encoded in "Rm": a
134710037SARM gem5 Developers    // 64-bit general register OR as '11111' for an immediate value equal to
134810037SARM gem5 Developers    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
134910037SARM gem5 Developers    if (wb) {
135010037SARM gem5 Developers        if (rm != ((RegIndex) INTREG_X31)) {
135110037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
135210037SARM gem5 Developers                                                      UXTX, 0);
135310037SARM gem5 Developers        } else {
135410037SARM gem5 Developers            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
135510037SARM gem5 Developers                                                   totNumBytes);
135610037SARM gem5 Developers        }
135710037SARM gem5 Developers    }
135810037SARM gem5 Developers
135910037SARM gem5 Developers    assert(uopIdx == numMicroops);
136010037SARM gem5 Developers
136110037SARM gem5 Developers    for (int i = 0; i < numMicroops - 1; i++) {
136210037SARM gem5 Developers        microOps[i]->setDelayedCommit();
136310037SARM gem5 Developers    }
136410037SARM gem5 Developers    microOps[numMicroops - 1]->setLastMicroop();
136510037SARM gem5 Developers}
136610037SARM gem5 Developers
13677175Sgblack@eecs.umich.eduMacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
13687175Sgblack@eecs.umich.edu                             OpClass __opClass, IntRegIndex rn,
13697175Sgblack@eecs.umich.edu                             RegIndex vd, bool single, bool up,
13707175Sgblack@eecs.umich.edu                             bool writeback, bool load, uint32_t offset) :
13717175Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
13727175Sgblack@eecs.umich.edu{
13737175Sgblack@eecs.umich.edu    int i = 0;
13747175Sgblack@eecs.umich.edu
13757175Sgblack@eecs.umich.edu    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
13767175Sgblack@eecs.umich.edu    // to be functionally identical except that fldmx is deprecated. For now
13777175Sgblack@eecs.umich.edu    // we'll assume they're otherwise interchangable.
13787175Sgblack@eecs.umich.edu    int count = (single ? offset : (offset / 2));
137910037SARM gem5 Developers    if (count == 0 || count > NumFloatV7ArchRegs)
13807175Sgblack@eecs.umich.edu        warn_once("Bad offset field for VFP load/store multiple.\n");
13817175Sgblack@eecs.umich.edu    if (count == 0) {
13827175Sgblack@eecs.umich.edu        // Force there to be at least one microop so the macroop makes sense.
13837175Sgblack@eecs.umich.edu        writeback = true;
13847175Sgblack@eecs.umich.edu    }
138510037SARM gem5 Developers    if (count > NumFloatV7ArchRegs)
138610037SARM gem5 Developers        count = NumFloatV7ArchRegs;
13877175Sgblack@eecs.umich.edu
13887342Sgblack@eecs.umich.edu    numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
13897342Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
13907342Sgblack@eecs.umich.edu
13917395Sgblack@eecs.umich.edu    int64_t addr = 0;
13927175Sgblack@eecs.umich.edu
13937342Sgblack@eecs.umich.edu    if (!up)
13947342Sgblack@eecs.umich.edu        addr = 4 * offset;
13957175Sgblack@eecs.umich.edu
13967342Sgblack@eecs.umich.edu    bool tempUp = up;
13977175Sgblack@eecs.umich.edu    for (int j = 0; j < count; j++) {
13987175Sgblack@eecs.umich.edu        if (load) {
13997639Sgblack@eecs.umich.edu            if (single) {
14007639Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
14017639Sgblack@eecs.umich.edu                                                  tempUp, addr);
14027639Sgblack@eecs.umich.edu            } else {
14037639Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn,
14047639Sgblack@eecs.umich.edu                                                    tempUp, addr);
14057639Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp,
14067639Sgblack@eecs.umich.edu                                                    addr + (up ? 4 : -4));
14077639Sgblack@eecs.umich.edu            }
14087175Sgblack@eecs.umich.edu        } else {
14097639Sgblack@eecs.umich.edu            if (single) {
14107639Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
14117639Sgblack@eecs.umich.edu                                                  tempUp, addr);
14127639Sgblack@eecs.umich.edu            } else {
14137639Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn,
14147639Sgblack@eecs.umich.edu                                                    tempUp, addr);
14157639Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp,
14167639Sgblack@eecs.umich.edu                                                    addr + (up ? 4 : -4));
14177639Sgblack@eecs.umich.edu            }
14187175Sgblack@eecs.umich.edu        }
14197342Sgblack@eecs.umich.edu        if (!tempUp) {
14207342Sgblack@eecs.umich.edu            addr -= (single ? 4 : 8);
14217342Sgblack@eecs.umich.edu            // The microops don't handle negative displacement, so turn if we
14227342Sgblack@eecs.umich.edu            // hit zero, flip polarity and start adding.
14237395Sgblack@eecs.umich.edu            if (addr <= 0) {
14247342Sgblack@eecs.umich.edu                tempUp = true;
14257395Sgblack@eecs.umich.edu                addr = -addr;
14267342Sgblack@eecs.umich.edu            }
14277342Sgblack@eecs.umich.edu        } else {
14287342Sgblack@eecs.umich.edu            addr += (single ? 4 : 8);
14297342Sgblack@eecs.umich.edu        }
14307175Sgblack@eecs.umich.edu    }
14317175Sgblack@eecs.umich.edu
14327175Sgblack@eecs.umich.edu    if (writeback) {
14337175Sgblack@eecs.umich.edu        if (up) {
14347175Sgblack@eecs.umich.edu            microOps[i++] =
14357175Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, 4 * offset);
14367175Sgblack@eecs.umich.edu        } else {
14377175Sgblack@eecs.umich.edu            microOps[i++] =
14387175Sgblack@eecs.umich.edu                new MicroSubiUop(machInst, rn, rn, 4 * offset);
14397175Sgblack@eecs.umich.edu        }
14407175Sgblack@eecs.umich.edu    }
14417175Sgblack@eecs.umich.edu
14427342Sgblack@eecs.umich.edu    assert(numMicroops == i);
14437175Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
14447343Sgblack@eecs.umich.edu
14457343Sgblack@eecs.umich.edu    for (StaticInstPtr *curUop = microOps;
14467343Sgblack@eecs.umich.edu            !(*curUop)->isLastMicroop(); curUop++) {
14477343Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
14487343Sgblack@eecs.umich.edu        assert(uopPtr);
14497343Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
14507343Sgblack@eecs.umich.edu    }
14517170Sgblack@eecs.umich.edu}
14527175Sgblack@eecs.umich.edu
14537615Sminkyu.jeong@arm.comstd::string
14547639Sgblack@eecs.umich.eduMicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14557639Sgblack@eecs.umich.edu{
14567639Sgblack@eecs.umich.edu    std::stringstream ss;
14577639Sgblack@eecs.umich.edu    printMnemonic(ss);
14587639Sgblack@eecs.umich.edu    printReg(ss, ura);
14597639Sgblack@eecs.umich.edu    ss << ", ";
14607639Sgblack@eecs.umich.edu    printReg(ss, urb);
14617639Sgblack@eecs.umich.edu    ss << ", ";
14627639Sgblack@eecs.umich.edu    ccprintf(ss, "#%d", imm);
14637639Sgblack@eecs.umich.edu    return ss.str();
14647639Sgblack@eecs.umich.edu}
14657639Sgblack@eecs.umich.edu
14667639Sgblack@eecs.umich.edustd::string
146710037SARM gem5 DevelopersMicroIntImmXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
146810037SARM gem5 Developers{
146910037SARM gem5 Developers    std::stringstream ss;
147010037SARM gem5 Developers    printMnemonic(ss);
147110037SARM gem5 Developers    printReg(ss, ura);
147210037SARM gem5 Developers    ss << ", ";
147310037SARM gem5 Developers    printReg(ss, urb);
147410037SARM gem5 Developers    ss << ", ";
147510037SARM gem5 Developers    ccprintf(ss, "#%d", imm);
147610037SARM gem5 Developers    return ss.str();
147710037SARM gem5 Developers}
147810037SARM gem5 Developers
147910037SARM gem5 Developersstd::string
14808140SMatt.Horsnell@arm.comMicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
14818140SMatt.Horsnell@arm.com{
14828140SMatt.Horsnell@arm.com    std::stringstream ss;
14838140SMatt.Horsnell@arm.com    printMnemonic(ss);
14848140SMatt.Horsnell@arm.com    ss << "[PC,CPSR]";
14858140SMatt.Horsnell@arm.com    return ss.str();
14868140SMatt.Horsnell@arm.com}
14878140SMatt.Horsnell@arm.com
14888140SMatt.Horsnell@arm.comstd::string
148910037SARM gem5 DevelopersMicroIntRegXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
149010037SARM gem5 Developers{
149110037SARM gem5 Developers    std::stringstream ss;
149210037SARM gem5 Developers    printMnemonic(ss);
149310037SARM gem5 Developers    printReg(ss, ura);
149410037SARM gem5 Developers    ccprintf(ss, ", ");
149510037SARM gem5 Developers    printReg(ss, urb);
149610037SARM gem5 Developers    printExtendOperand(false, ss, (IntRegIndex)urc, type, shiftAmt);
149710037SARM gem5 Developers    return ss.str();
149810037SARM gem5 Developers}
149910037SARM gem5 Developers
150010037SARM gem5 Developersstd::string
15017646Sgene.wu@arm.comMicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
15027646Sgene.wu@arm.com{
15037646Sgene.wu@arm.com    std::stringstream ss;
15047646Sgene.wu@arm.com    printMnemonic(ss);
15057646Sgene.wu@arm.com    printReg(ss, ura);
15067646Sgene.wu@arm.com    ss << ", ";
15077646Sgene.wu@arm.com    printReg(ss, urb);
15087646Sgene.wu@arm.com    return ss.str();
15097646Sgene.wu@arm.com}
15107646Sgene.wu@arm.com
15117646Sgene.wu@arm.comstd::string
15127615Sminkyu.jeong@arm.comMicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
15137615Sminkyu.jeong@arm.com{
15147615Sminkyu.jeong@arm.com    std::stringstream ss;
15157615Sminkyu.jeong@arm.com    printMnemonic(ss);
15167615Sminkyu.jeong@arm.com    printReg(ss, ura);
15177615Sminkyu.jeong@arm.com    ss << ", ";
15187615Sminkyu.jeong@arm.com    printReg(ss, urb);
15197615Sminkyu.jeong@arm.com    ss << ", ";
15207639Sgblack@eecs.umich.edu    printReg(ss, urc);
15217615Sminkyu.jeong@arm.com    return ss.str();
15227175Sgblack@eecs.umich.edu}
15237615Sminkyu.jeong@arm.com
15247615Sminkyu.jeong@arm.comstd::string
15257615Sminkyu.jeong@arm.comMicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
15267615Sminkyu.jeong@arm.com{
15277615Sminkyu.jeong@arm.com    std::stringstream ss;
15287615Sminkyu.jeong@arm.com    printMnemonic(ss);
152910180SCurtis.Dunham@arm.com    if (isFloating())
153010180SCurtis.Dunham@arm.com        printReg(ss, ura + FP_Reg_Base);
153110180SCurtis.Dunham@arm.com    else
153210180SCurtis.Dunham@arm.com        printReg(ss, ura);
15337615Sminkyu.jeong@arm.com    ss << ", [";
15347615Sminkyu.jeong@arm.com    printReg(ss, urb);
15357615Sminkyu.jeong@arm.com    ss << ", ";
15367615Sminkyu.jeong@arm.com    ccprintf(ss, "#%d", imm);
15377615Sminkyu.jeong@arm.com    ss << "]";
15387615Sminkyu.jeong@arm.com    return ss.str();
15397615Sminkyu.jeong@arm.com}
15407615Sminkyu.jeong@arm.com
15417615Sminkyu.jeong@arm.com}
1542