macromem.cc revision 10339:53278be85b40
110259SAndrew.Bardsley@arm.com/*
210259SAndrew.Bardsley@arm.com * Copyright (c) 2010-2014 ARM Limited
310259SAndrew.Bardsley@arm.com * All rights reserved
410259SAndrew.Bardsley@arm.com *
510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall
610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual
710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating
810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software
910259SAndrew.Bardsley@arm.com * licensed hereunder.  You may use the software subject to the license
1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated
1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software,
1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form.
1310259SAndrew.Bardsley@arm.com *
1410259SAndrew.Bardsley@arm.com * Copyright (c) 2007-2008 The Florida State University
1510259SAndrew.Bardsley@arm.com * All rights reserved.
1610259SAndrew.Bardsley@arm.com *
1710259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
1810259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
1910259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
2010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
2110259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
2210259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
2310259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
2410259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
2510259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
2610259SAndrew.Bardsley@arm.com * this software without specific prior written permission.
2710259SAndrew.Bardsley@arm.com *
2810259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2910259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3010259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3110259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3210259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3310259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3410259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3510259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3610259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3710259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3810259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3910259SAndrew.Bardsley@arm.com *
4010259SAndrew.Bardsley@arm.com * Authors: Stephen Hines
4110259SAndrew.Bardsley@arm.com */
4210259SAndrew.Bardsley@arm.com
4310259SAndrew.Bardsley@arm.com#include <sstream>
4410259SAndrew.Bardsley@arm.com
4510259SAndrew.Bardsley@arm.com#include "arch/arm/insts/macromem.hh"
4610259SAndrew.Bardsley@arm.com
4710259SAndrew.Bardsley@arm.com#include "arch/arm/generated/decoder.hh"
4810259SAndrew.Bardsley@arm.com#include "arch/arm/insts/neon64_mem.hh"
4910259SAndrew.Bardsley@arm.com
5010259SAndrew.Bardsley@arm.comusing namespace std;
5110259SAndrew.Bardsley@arm.comusing namespace ArmISAInst;
5210259SAndrew.Bardsley@arm.com
5310259SAndrew.Bardsley@arm.comnamespace ArmISA
5410259SAndrew.Bardsley@arm.com{
5510259SAndrew.Bardsley@arm.com
5610259SAndrew.Bardsley@arm.comMacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
5710259SAndrew.Bardsley@arm.com                       OpClass __opClass, IntRegIndex rn,
5810259SAndrew.Bardsley@arm.com                       bool index, bool up, bool user, bool writeback,
5910259SAndrew.Bardsley@arm.com                       bool load, uint32_t reglist) :
6010259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
6110259SAndrew.Bardsley@arm.com{
6210259SAndrew.Bardsley@arm.com    uint32_t regs = reglist;
6310259SAndrew.Bardsley@arm.com    uint32_t ones = number_of_ones(reglist);
6410259SAndrew.Bardsley@arm.com    // Remember that writeback adds a uop or two and the temp register adds one
6510259SAndrew.Bardsley@arm.com    numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1;
6610259SAndrew.Bardsley@arm.com
6710259SAndrew.Bardsley@arm.com    // It's technically legal to do a lot of nothing
6810259SAndrew.Bardsley@arm.com    if (!ones)
6910259SAndrew.Bardsley@arm.com        numMicroops = 1;
7010259SAndrew.Bardsley@arm.com
7110259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
7210259SAndrew.Bardsley@arm.com    uint32_t addr = 0;
7310259SAndrew.Bardsley@arm.com
7410259SAndrew.Bardsley@arm.com    if (!up)
7510259SAndrew.Bardsley@arm.com        addr = (ones << 2) - 4;
7610259SAndrew.Bardsley@arm.com
7710259SAndrew.Bardsley@arm.com    if (!index)
7810259SAndrew.Bardsley@arm.com        addr += 4;
7910259SAndrew.Bardsley@arm.com
8010259SAndrew.Bardsley@arm.com    StaticInstPtr *uop = microOps;
8110259SAndrew.Bardsley@arm.com
8210259SAndrew.Bardsley@arm.com    // Add 0 to Rn and stick it in ureg0.
8310259SAndrew.Bardsley@arm.com    // This is equivalent to a move.
8410259SAndrew.Bardsley@arm.com    *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
8510259SAndrew.Bardsley@arm.com
8610259SAndrew.Bardsley@arm.com    unsigned reg = 0;
8710259SAndrew.Bardsley@arm.com    unsigned regIdx = 0;
8810259SAndrew.Bardsley@arm.com    bool force_user = user & !bits(reglist, 15);
8910259SAndrew.Bardsley@arm.com    bool exception_ret = user & bits(reglist, 15);
9010259SAndrew.Bardsley@arm.com
9110259SAndrew.Bardsley@arm.com    for (int i = 0; i < ones; i++) {
9210259SAndrew.Bardsley@arm.com        // Find the next register.
9310259SAndrew.Bardsley@arm.com        while (!bits(regs, reg))
9410259SAndrew.Bardsley@arm.com            reg++;
9510259SAndrew.Bardsley@arm.com        replaceBits(regs, reg, 0);
9610259SAndrew.Bardsley@arm.com
9710259SAndrew.Bardsley@arm.com        regIdx = reg;
9810259SAndrew.Bardsley@arm.com        if (force_user) {
9910259SAndrew.Bardsley@arm.com            regIdx = intRegInMode(MODE_USER, regIdx);
10010259SAndrew.Bardsley@arm.com        }
10110259SAndrew.Bardsley@arm.com
10210259SAndrew.Bardsley@arm.com        if (load) {
10310259SAndrew.Bardsley@arm.com            if (writeback && i == ones - 1) {
10410259SAndrew.Bardsley@arm.com                // If it's a writeback and this is the last register
10510259SAndrew.Bardsley@arm.com                // do the load into a temporary register which we'll move
10610259SAndrew.Bardsley@arm.com                // into the final one later
10710259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0,
10810259SAndrew.Bardsley@arm.com                        up, addr);
10910259SAndrew.Bardsley@arm.com            } else {
11010259SAndrew.Bardsley@arm.com                // Otherwise just do it normally
11110259SAndrew.Bardsley@arm.com                if (reg == INTREG_PC && exception_ret) {
11210259SAndrew.Bardsley@arm.com                    // This must be the exception return form of ldm.
11310259SAndrew.Bardsley@arm.com                    *++uop = new MicroLdrRetUop(machInst, regIdx,
11410259SAndrew.Bardsley@arm.com                                               INTREG_UREG0, up, addr);
11510259SAndrew.Bardsley@arm.com                    if (!(condCode == COND_AL || condCode == COND_UC))
11610259SAndrew.Bardsley@arm.com                        (*uop)->setFlag(StaticInst::IsCondControl);
11710259SAndrew.Bardsley@arm.com                    else
11810259SAndrew.Bardsley@arm.com                        (*uop)->setFlag(StaticInst::IsUncondControl);
11910259SAndrew.Bardsley@arm.com                } else {
12010259SAndrew.Bardsley@arm.com                    *++uop = new MicroLdrUop(machInst, regIdx,
12110259SAndrew.Bardsley@arm.com                                            INTREG_UREG0, up, addr);
12210259SAndrew.Bardsley@arm.com                    if (reg == INTREG_PC) {
12310259SAndrew.Bardsley@arm.com                        (*uop)->setFlag(StaticInst::IsControl);
12410259SAndrew.Bardsley@arm.com                        if (!(condCode == COND_AL || condCode == COND_UC))
12510259SAndrew.Bardsley@arm.com                            (*uop)->setFlag(StaticInst::IsCondControl);
12610259SAndrew.Bardsley@arm.com                        else
12710259SAndrew.Bardsley@arm.com                            (*uop)->setFlag(StaticInst::IsUncondControl);
12810259SAndrew.Bardsley@arm.com                        (*uop)->setFlag(StaticInst::IsIndirectControl);
12910259SAndrew.Bardsley@arm.com                    }
13010259SAndrew.Bardsley@arm.com                }
13110259SAndrew.Bardsley@arm.com            }
13210259SAndrew.Bardsley@arm.com        } else {
13310259SAndrew.Bardsley@arm.com            *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
13410259SAndrew.Bardsley@arm.com        }
13510259SAndrew.Bardsley@arm.com
13610259SAndrew.Bardsley@arm.com        if (up)
13710259SAndrew.Bardsley@arm.com            addr += 4;
13810259SAndrew.Bardsley@arm.com        else
13910259SAndrew.Bardsley@arm.com            addr -= 4;
14010259SAndrew.Bardsley@arm.com    }
14110259SAndrew.Bardsley@arm.com
14210259SAndrew.Bardsley@arm.com    if (writeback && ones) {
14310259SAndrew.Bardsley@arm.com        // put the register update after we're done all loading
14410259SAndrew.Bardsley@arm.com        if (up)
14510259SAndrew.Bardsley@arm.com            *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4);
14610259SAndrew.Bardsley@arm.com        else
14710259SAndrew.Bardsley@arm.com            *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4);
14810259SAndrew.Bardsley@arm.com
14910259SAndrew.Bardsley@arm.com        // If this was a load move the last temporary value into place
15010259SAndrew.Bardsley@arm.com        // this way we can't take an exception after we update the base
15110259SAndrew.Bardsley@arm.com        // register.
15210259SAndrew.Bardsley@arm.com        if (load && reg == INTREG_PC && exception_ret) {
15310259SAndrew.Bardsley@arm.com            *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
15410259SAndrew.Bardsley@arm.com            if (!(condCode == COND_AL || condCode == COND_UC))
15510259SAndrew.Bardsley@arm.com                (*uop)->setFlag(StaticInst::IsCondControl);
15610259SAndrew.Bardsley@arm.com            else
15710259SAndrew.Bardsley@arm.com                (*uop)->setFlag(StaticInst::IsUncondControl);
15810259SAndrew.Bardsley@arm.com        } else if (load) {
15910259SAndrew.Bardsley@arm.com            *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1);
16010259SAndrew.Bardsley@arm.com            if (reg == INTREG_PC) {
16110259SAndrew.Bardsley@arm.com                (*uop)->setFlag(StaticInst::IsControl);
16210259SAndrew.Bardsley@arm.com                (*uop)->setFlag(StaticInst::IsCondControl);
16310259SAndrew.Bardsley@arm.com                (*uop)->setFlag(StaticInst::IsIndirectControl);
16410259SAndrew.Bardsley@arm.com                // This is created as a RAS POP
16510259SAndrew.Bardsley@arm.com                if (rn == INTREG_SP)
16610259SAndrew.Bardsley@arm.com                    (*uop)->setFlag(StaticInst::IsReturn);
16710259SAndrew.Bardsley@arm.com
16810259SAndrew.Bardsley@arm.com            }
16910259SAndrew.Bardsley@arm.com        }
17010259SAndrew.Bardsley@arm.com    }
17110259SAndrew.Bardsley@arm.com
17210259SAndrew.Bardsley@arm.com    (*uop)->setLastMicroop();
17310259SAndrew.Bardsley@arm.com
17410259SAndrew.Bardsley@arm.com    /* Take the control flags from the last microop for the macroop */
17510259SAndrew.Bardsley@arm.com    if ((*uop)->isControl())
17610259SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsControl);
17710259SAndrew.Bardsley@arm.com    if ((*uop)->isCondCtrl())
17810259SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsCondControl);
17910259SAndrew.Bardsley@arm.com    if ((*uop)->isIndirectCtrl())
18010259SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsIndirectControl);
18110259SAndrew.Bardsley@arm.com    if ((*uop)->isReturn())
18210259SAndrew.Bardsley@arm.com        setFlag(StaticInst::IsReturn);
18310259SAndrew.Bardsley@arm.com
18410259SAndrew.Bardsley@arm.com    for (StaticInstPtr *curUop = microOps;
18510259SAndrew.Bardsley@arm.com            !(*curUop)->isLastMicroop(); curUop++) {
18610259SAndrew.Bardsley@arm.com        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
18710259SAndrew.Bardsley@arm.com        assert(uopPtr);
18810259SAndrew.Bardsley@arm.com        uopPtr->setDelayedCommit();
18910259SAndrew.Bardsley@arm.com    }
19010259SAndrew.Bardsley@arm.com}
19110259SAndrew.Bardsley@arm.com
19210259SAndrew.Bardsley@arm.comPairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
19310259SAndrew.Bardsley@arm.com                     uint32_t size, bool fp, bool load, bool noAlloc,
19410259SAndrew.Bardsley@arm.com                     bool signExt, bool exclusive, bool acrel,
19510259SAndrew.Bardsley@arm.com                     int64_t imm, AddrMode mode,
19610259SAndrew.Bardsley@arm.com                     IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) :
19710259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
19810259SAndrew.Bardsley@arm.com{
19910259SAndrew.Bardsley@arm.com    bool writeback = (mode != AddrMd_Offset);
20010259SAndrew.Bardsley@arm.com    numMicroops = 1 + (size / 4) + (writeback ? 1 : 0);
20110259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
20210259SAndrew.Bardsley@arm.com
20310259SAndrew.Bardsley@arm.com    StaticInstPtr *uop = microOps;
20410259SAndrew.Bardsley@arm.com
20510259SAndrew.Bardsley@arm.com    bool post = (mode == AddrMd_PostIndex);
20610259SAndrew.Bardsley@arm.com
20710259SAndrew.Bardsley@arm.com    rn = makeSP(rn);
20810259SAndrew.Bardsley@arm.com
20910259SAndrew.Bardsley@arm.com    *uop = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, post ? 0 : imm);
21010259SAndrew.Bardsley@arm.com
21110259SAndrew.Bardsley@arm.com    if (fp) {
21210259SAndrew.Bardsley@arm.com        if (size == 16) {
21310259SAndrew.Bardsley@arm.com            if (load) {
21410259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrQBFpXImmUop(machInst, rt,
21510259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21610259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrQTFpXImmUop(machInst, rt,
21710259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
21810259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrQBFpXImmUop(machInst, rt2,
21910259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22010259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrQTFpXImmUop(machInst, rt2,
22110259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22210259SAndrew.Bardsley@arm.com            } else {
22310259SAndrew.Bardsley@arm.com                *++uop = new MicroStrQBFpXImmUop(machInst, rt,
22410259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
22510259SAndrew.Bardsley@arm.com                *++uop = new MicroStrQTFpXImmUop(machInst, rt,
22610259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
22710259SAndrew.Bardsley@arm.com                *++uop = new MicroStrQBFpXImmUop(machInst, rt2,
22810259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
22910259SAndrew.Bardsley@arm.com                *++uop = new MicroStrQTFpXImmUop(machInst, rt2,
23010259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 16, noAlloc, exclusive, acrel);
23110259SAndrew.Bardsley@arm.com            }
23210259SAndrew.Bardsley@arm.com        } else if (size == 8) {
23310259SAndrew.Bardsley@arm.com            if (load) {
23410259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrFpXImmUop(machInst, rt,
23510259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
23610259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrFpXImmUop(machInst, rt2,
23710259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
23810259SAndrew.Bardsley@arm.com            } else {
23910259SAndrew.Bardsley@arm.com                *++uop = new MicroStrFpXImmUop(machInst, rt,
24010259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
24110259SAndrew.Bardsley@arm.com                *++uop = new MicroStrFpXImmUop(machInst, rt2,
24210259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 8, noAlloc, exclusive, acrel);
24310259SAndrew.Bardsley@arm.com            }
24410259SAndrew.Bardsley@arm.com        } else if (size == 4) {
24510259SAndrew.Bardsley@arm.com            if (load) {
24610259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrDFpXImmUop(machInst, rt, rt2,
24710259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
24810259SAndrew.Bardsley@arm.com            } else {
24910259SAndrew.Bardsley@arm.com                *++uop = new MicroStrDFpXImmUop(machInst, rt, rt2,
25010259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
25110259SAndrew.Bardsley@arm.com            }
25210259SAndrew.Bardsley@arm.com        }
25310259SAndrew.Bardsley@arm.com    } else {
25410259SAndrew.Bardsley@arm.com        if (size == 8) {
25510259SAndrew.Bardsley@arm.com            if (load) {
25610259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrXImmUop(machInst, rt, INTREG_UREG0,
25710259SAndrew.Bardsley@arm.com                        0, noAlloc, exclusive, acrel);
25810259SAndrew.Bardsley@arm.com                *++uop = new MicroLdrXImmUop(machInst, rt2, INTREG_UREG0,
25910259SAndrew.Bardsley@arm.com                        size, noAlloc, exclusive, acrel);
26010259SAndrew.Bardsley@arm.com            } else {
26110259SAndrew.Bardsley@arm.com                *++uop = new MicroStrXImmUop(machInst, rt, INTREG_UREG0,
26210259SAndrew.Bardsley@arm.com                        0, noAlloc, exclusive, acrel);
26310259SAndrew.Bardsley@arm.com                *++uop = new MicroStrXImmUop(machInst, rt2, INTREG_UREG0,
26410259SAndrew.Bardsley@arm.com                        size, noAlloc, exclusive, acrel);
26510259SAndrew.Bardsley@arm.com            }
26610259SAndrew.Bardsley@arm.com        } else if (size == 4) {
26710259SAndrew.Bardsley@arm.com            if (load) {
26810259SAndrew.Bardsley@arm.com                if (signExt) {
26910259SAndrew.Bardsley@arm.com                    *++uop = new MicroLdrDSXImmUop(machInst, rt, rt2,
27010259SAndrew.Bardsley@arm.com                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27110259SAndrew.Bardsley@arm.com                } else {
27210259SAndrew.Bardsley@arm.com                    *++uop = new MicroLdrDUXImmUop(machInst, rt, rt2,
27310259SAndrew.Bardsley@arm.com                            INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27410259SAndrew.Bardsley@arm.com                }
27510259SAndrew.Bardsley@arm.com            } else {
27610259SAndrew.Bardsley@arm.com                *++uop = new MicroStrDXImmUop(machInst, rt, rt2,
27710259SAndrew.Bardsley@arm.com                        INTREG_UREG0, 0, noAlloc, exclusive, acrel);
27810259SAndrew.Bardsley@arm.com            }
27910259SAndrew.Bardsley@arm.com        }
28010259SAndrew.Bardsley@arm.com    }
28110259SAndrew.Bardsley@arm.com
28210259SAndrew.Bardsley@arm.com    if (writeback) {
28310259SAndrew.Bardsley@arm.com        *++uop = new MicroAddXiUop(machInst, rn, INTREG_UREG0,
28410259SAndrew.Bardsley@arm.com                                   post ? imm : 0);
28510259SAndrew.Bardsley@arm.com    }
28610259SAndrew.Bardsley@arm.com
28710259SAndrew.Bardsley@arm.com    (*uop)->setLastMicroop();
28810259SAndrew.Bardsley@arm.com
28910259SAndrew.Bardsley@arm.com    for (StaticInstPtr *curUop = microOps;
29010259SAndrew.Bardsley@arm.com            !(*curUop)->isLastMicroop(); curUop++) {
29110259SAndrew.Bardsley@arm.com        (*curUop)->setDelayedCommit();
29210259SAndrew.Bardsley@arm.com    }
29310259SAndrew.Bardsley@arm.com}
29410259SAndrew.Bardsley@arm.com
29510259SAndrew.Bardsley@arm.comBigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst,
29610259SAndrew.Bardsley@arm.com                             OpClass __opClass, bool load, IntRegIndex dest,
29710259SAndrew.Bardsley@arm.com                             IntRegIndex base, int64_t imm) :
29810259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
29910259SAndrew.Bardsley@arm.com{
30010259SAndrew.Bardsley@arm.com    numMicroops = 2;
30110259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
30210259SAndrew.Bardsley@arm.com
30310259SAndrew.Bardsley@arm.com    if (load) {
30410259SAndrew.Bardsley@arm.com        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
30510259SAndrew.Bardsley@arm.com        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
30610259SAndrew.Bardsley@arm.com    } else {
30710259SAndrew.Bardsley@arm.com        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
30810259SAndrew.Bardsley@arm.com        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
30910259SAndrew.Bardsley@arm.com    }
31010259SAndrew.Bardsley@arm.com    microOps[0]->setDelayedCommit();
31110259SAndrew.Bardsley@arm.com    microOps[1]->setLastMicroop();
31210259SAndrew.Bardsley@arm.com}
31310259SAndrew.Bardsley@arm.com
31410259SAndrew.Bardsley@arm.comBigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst,
31510259SAndrew.Bardsley@arm.com                               OpClass __opClass, bool load, IntRegIndex dest,
31610259SAndrew.Bardsley@arm.com                               IntRegIndex base, int64_t imm) :
31710259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
31810259SAndrew.Bardsley@arm.com{
31910259SAndrew.Bardsley@arm.com    numMicroops = 3;
32010259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
32110259SAndrew.Bardsley@arm.com
32210259SAndrew.Bardsley@arm.com    if (load) {
32310259SAndrew.Bardsley@arm.com        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, 0);
32410259SAndrew.Bardsley@arm.com        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, 0);
32510259SAndrew.Bardsley@arm.com    } else {
32610259SAndrew.Bardsley@arm.com        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, 0);
32710259SAndrew.Bardsley@arm.com        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, 0);
32810259SAndrew.Bardsley@arm.com    }
32910259SAndrew.Bardsley@arm.com    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
33010259SAndrew.Bardsley@arm.com
33110259SAndrew.Bardsley@arm.com    microOps[0]->setDelayedCommit();
33210259SAndrew.Bardsley@arm.com    microOps[1]->setDelayedCommit();
33310259SAndrew.Bardsley@arm.com    microOps[2]->setLastMicroop();
33410259SAndrew.Bardsley@arm.com}
33510259SAndrew.Bardsley@arm.com
33610259SAndrew.Bardsley@arm.comBigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst,
33710259SAndrew.Bardsley@arm.com                             OpClass __opClass, bool load, IntRegIndex dest,
33810259SAndrew.Bardsley@arm.com                             IntRegIndex base, int64_t imm) :
33910259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
34010259SAndrew.Bardsley@arm.com{
34110259SAndrew.Bardsley@arm.com    numMicroops = 3;
34210259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
34310259SAndrew.Bardsley@arm.com
34410259SAndrew.Bardsley@arm.com    if (load) {
34510259SAndrew.Bardsley@arm.com        microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
34610259SAndrew.Bardsley@arm.com        microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
34710259SAndrew.Bardsley@arm.com    } else {
34810259SAndrew.Bardsley@arm.com        microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
34910259SAndrew.Bardsley@arm.com        microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
35010259SAndrew.Bardsley@arm.com    }
35110259SAndrew.Bardsley@arm.com    microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
35210259SAndrew.Bardsley@arm.com
35310259SAndrew.Bardsley@arm.com    microOps[0]->setDelayedCommit();
35410259SAndrew.Bardsley@arm.com    microOps[1]->setDelayedCommit();
35510259SAndrew.Bardsley@arm.com    microOps[2]->setLastMicroop();
35610259SAndrew.Bardsley@arm.com}
35710259SAndrew.Bardsley@arm.com
35810259SAndrew.Bardsley@arm.comBigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst,
35910259SAndrew.Bardsley@arm.com                             OpClass __opClass, bool load, IntRegIndex dest,
36010259SAndrew.Bardsley@arm.com                             IntRegIndex base, IntRegIndex offset,
36110259SAndrew.Bardsley@arm.com                             ArmExtendType type, int64_t imm) :
36210259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
36310259SAndrew.Bardsley@arm.com{
36410259SAndrew.Bardsley@arm.com    numMicroops = 2;
36510259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
36610259SAndrew.Bardsley@arm.com
36710259SAndrew.Bardsley@arm.com    if (load) {
36810259SAndrew.Bardsley@arm.com        microOps[0] = new MicroLdrQBFpXRegUop(machInst, dest, base,
36910259SAndrew.Bardsley@arm.com                                              offset, type, imm);
37010259SAndrew.Bardsley@arm.com        microOps[1] = new MicroLdrQTFpXRegUop(machInst, dest, base,
37110259SAndrew.Bardsley@arm.com                                              offset, type, imm);
37210259SAndrew.Bardsley@arm.com    } else {
37310259SAndrew.Bardsley@arm.com        microOps[0] = new MicroStrQBFpXRegUop(machInst, dest, base,
37410259SAndrew.Bardsley@arm.com                                              offset, type, imm);
37510259SAndrew.Bardsley@arm.com        microOps[1] = new MicroStrQTFpXRegUop(machInst, dest, base,
37610259SAndrew.Bardsley@arm.com                                              offset, type, imm);
37710259SAndrew.Bardsley@arm.com    }
37810259SAndrew.Bardsley@arm.com
37910259SAndrew.Bardsley@arm.com    microOps[0]->setDelayedCommit();
38010259SAndrew.Bardsley@arm.com    microOps[1]->setLastMicroop();
38110259SAndrew.Bardsley@arm.com}
38210259SAndrew.Bardsley@arm.com
38310259SAndrew.Bardsley@arm.comBigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst,
38410259SAndrew.Bardsley@arm.com                             OpClass __opClass, IntRegIndex dest,
38510259SAndrew.Bardsley@arm.com                             int64_t imm) :
38610259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
38710259SAndrew.Bardsley@arm.com{
38810259SAndrew.Bardsley@arm.com    numMicroops = 2;
38910259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
39010259SAndrew.Bardsley@arm.com
39110259SAndrew.Bardsley@arm.com    microOps[0] = new MicroLdrQBFpXLitUop(machInst, dest, imm);
39210259SAndrew.Bardsley@arm.com    microOps[1] = new MicroLdrQTFpXLitUop(machInst, dest, imm);
39310259SAndrew.Bardsley@arm.com
39410259SAndrew.Bardsley@arm.com    microOps[0]->setDelayedCommit();
39510259SAndrew.Bardsley@arm.com    microOps[1]->setLastMicroop();
39610259SAndrew.Bardsley@arm.com}
39710259SAndrew.Bardsley@arm.com
39810259SAndrew.Bardsley@arm.comVldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
39910259SAndrew.Bardsley@arm.com                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
40010259SAndrew.Bardsley@arm.com                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
40110259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
40210259SAndrew.Bardsley@arm.com{
40310259SAndrew.Bardsley@arm.com    assert(regs > 0 && regs <= 4);
40410259SAndrew.Bardsley@arm.com    assert(regs % elems == 0);
40510259SAndrew.Bardsley@arm.com
40610259SAndrew.Bardsley@arm.com    numMicroops = (regs > 2) ? 2 : 1;
40710259SAndrew.Bardsley@arm.com    bool wb = (rm != 15);
40810259SAndrew.Bardsley@arm.com    bool deinterleave = (elems > 1);
40910259SAndrew.Bardsley@arm.com
41010259SAndrew.Bardsley@arm.com    if (wb) numMicroops++;
41110259SAndrew.Bardsley@arm.com    if (deinterleave) numMicroops += (regs / elems);
41210259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
41310259SAndrew.Bardsley@arm.com
41410259SAndrew.Bardsley@arm.com    RegIndex rMid = deinterleave ? NumFloatV7ArchRegs : vd * 2;
41510259SAndrew.Bardsley@arm.com
41610259SAndrew.Bardsley@arm.com    uint32_t noAlign = TLB::MustBeOne;
41710259SAndrew.Bardsley@arm.com
41810259SAndrew.Bardsley@arm.com    unsigned uopIdx = 0;
41910259SAndrew.Bardsley@arm.com    switch (regs) {
42010259SAndrew.Bardsley@arm.com      case 4:
42110259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
42210259SAndrew.Bardsley@arm.com                size, machInst, rMid, rn, 0, align);
42310259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
42410259SAndrew.Bardsley@arm.com                size, machInst, rMid + 4, rn, 16, noAlign);
42510259SAndrew.Bardsley@arm.com        break;
42610259SAndrew.Bardsley@arm.com      case 3:
42710259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
42810259SAndrew.Bardsley@arm.com                size, machInst, rMid, rn, 0, align);
42910259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
43010259SAndrew.Bardsley@arm.com                size, machInst, rMid + 4, rn, 16, noAlign);
43110259SAndrew.Bardsley@arm.com        break;
43210259SAndrew.Bardsley@arm.com      case 2:
43310259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
43410259SAndrew.Bardsley@arm.com                size, machInst, rMid, rn, 0, align);
43510259SAndrew.Bardsley@arm.com        break;
43610259SAndrew.Bardsley@arm.com      case 1:
43710259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
43810259SAndrew.Bardsley@arm.com                size, machInst, rMid, rn, 0, align);
43910259SAndrew.Bardsley@arm.com        break;
44010259SAndrew.Bardsley@arm.com      default:
44110259SAndrew.Bardsley@arm.com        // Unknown number of registers
44210259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = new Unknown(machInst);
44310259SAndrew.Bardsley@arm.com    }
44410259SAndrew.Bardsley@arm.com    if (wb) {
44510259SAndrew.Bardsley@arm.com        if (rm != 15 && rm != 13) {
44610259SAndrew.Bardsley@arm.com            microOps[uopIdx++] =
44710259SAndrew.Bardsley@arm.com                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
44810259SAndrew.Bardsley@arm.com        } else {
44910259SAndrew.Bardsley@arm.com            microOps[uopIdx++] =
45010259SAndrew.Bardsley@arm.com                new MicroAddiUop(machInst, rn, rn, regs * 8);
45110259SAndrew.Bardsley@arm.com        }
45210259SAndrew.Bardsley@arm.com    }
45310259SAndrew.Bardsley@arm.com    if (deinterleave) {
45410259SAndrew.Bardsley@arm.com        switch (elems) {
45510259SAndrew.Bardsley@arm.com          case 4:
45610259SAndrew.Bardsley@arm.com            assert(regs == 4);
45710259SAndrew.Bardsley@arm.com            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>(
45810259SAndrew.Bardsley@arm.com                    size, machInst, vd * 2, rMid, inc * 2);
45910259SAndrew.Bardsley@arm.com            break;
46010259SAndrew.Bardsley@arm.com          case 3:
46110259SAndrew.Bardsley@arm.com            assert(regs == 3);
46210259SAndrew.Bardsley@arm.com            microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>(
46310259SAndrew.Bardsley@arm.com                    size, machInst, vd * 2, rMid, inc * 2);
46410259SAndrew.Bardsley@arm.com            break;
46510259SAndrew.Bardsley@arm.com          case 2:
46610259SAndrew.Bardsley@arm.com            assert(regs == 4 || regs == 2);
46710259SAndrew.Bardsley@arm.com            if (regs == 4) {
46810259SAndrew.Bardsley@arm.com                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
46910259SAndrew.Bardsley@arm.com                        size, machInst, vd * 2, rMid, inc * 2);
47010259SAndrew.Bardsley@arm.com                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
47110259SAndrew.Bardsley@arm.com                        size, machInst, vd * 2 + 2, rMid + 4, inc * 2);
47210259SAndrew.Bardsley@arm.com            } else {
47310259SAndrew.Bardsley@arm.com                microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
47410259SAndrew.Bardsley@arm.com                        size, machInst, vd * 2, rMid, inc * 2);
47510259SAndrew.Bardsley@arm.com            }
47610259SAndrew.Bardsley@arm.com            break;
47710259SAndrew.Bardsley@arm.com          default:
47810259SAndrew.Bardsley@arm.com            // Bad number of elements to deinterleave
47910259SAndrew.Bardsley@arm.com            microOps[uopIdx++] = new Unknown(machInst);
48010259SAndrew.Bardsley@arm.com        }
48110259SAndrew.Bardsley@arm.com    }
48210259SAndrew.Bardsley@arm.com    assert(uopIdx == numMicroops);
48310259SAndrew.Bardsley@arm.com
48410259SAndrew.Bardsley@arm.com    for (unsigned i = 0; i < numMicroops - 1; i++) {
48510259SAndrew.Bardsley@arm.com        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
48610259SAndrew.Bardsley@arm.com        assert(uopPtr);
48710259SAndrew.Bardsley@arm.com        uopPtr->setDelayedCommit();
48810259SAndrew.Bardsley@arm.com    }
48910259SAndrew.Bardsley@arm.com    microOps[numMicroops - 1]->setLastMicroop();
49010259SAndrew.Bardsley@arm.com}
49110259SAndrew.Bardsley@arm.com
49210259SAndrew.Bardsley@arm.comVldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
49310259SAndrew.Bardsley@arm.com                         OpClass __opClass, bool all, unsigned elems,
49410259SAndrew.Bardsley@arm.com                         RegIndex rn, RegIndex vd, unsigned regs,
49510259SAndrew.Bardsley@arm.com                         unsigned inc, uint32_t size, uint32_t align,
49610259SAndrew.Bardsley@arm.com                         RegIndex rm, unsigned lane) :
49710259SAndrew.Bardsley@arm.com    PredMacroOp(mnem, machInst, __opClass)
49810259SAndrew.Bardsley@arm.com{
49910259SAndrew.Bardsley@arm.com    assert(regs > 0 && regs <= 4);
50010259SAndrew.Bardsley@arm.com    assert(regs % elems == 0);
50110259SAndrew.Bardsley@arm.com
50210259SAndrew.Bardsley@arm.com    unsigned eBytes = (1 << size);
50310259SAndrew.Bardsley@arm.com    unsigned loadSize = eBytes * elems;
50410259SAndrew.Bardsley@arm.com    unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) /
50510259SAndrew.Bardsley@arm.com                        sizeof(FloatRegBits);
50610259SAndrew.Bardsley@arm.com
50710259SAndrew.Bardsley@arm.com    assert(loadRegs > 0 && loadRegs <= 4);
50810259SAndrew.Bardsley@arm.com
50910259SAndrew.Bardsley@arm.com    numMicroops = 1;
51010259SAndrew.Bardsley@arm.com    bool wb = (rm != 15);
51110259SAndrew.Bardsley@arm.com
51210259SAndrew.Bardsley@arm.com    if (wb) numMicroops++;
51310259SAndrew.Bardsley@arm.com    numMicroops += (regs / elems);
51410259SAndrew.Bardsley@arm.com    microOps = new StaticInstPtr[numMicroops];
51510259SAndrew.Bardsley@arm.com
51610259SAndrew.Bardsley@arm.com    RegIndex ufp0 = NumFloatV7ArchRegs;
51710259SAndrew.Bardsley@arm.com
51810259SAndrew.Bardsley@arm.com    unsigned uopIdx = 0;
51910259SAndrew.Bardsley@arm.com    switch (loadSize) {
52010259SAndrew.Bardsley@arm.com      case 1:
52110259SAndrew.Bardsley@arm.com        microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>(
52210259SAndrew.Bardsley@arm.com                machInst, ufp0, rn, 0, align);
52310259SAndrew.Bardsley@arm.com        break;
52410259SAndrew.Bardsley@arm.com      case 2:
525        if (eBytes == 2) {
526            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>(
527                    machInst, ufp0, rn, 0, align);
528        } else {
529            microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>(
530                    machInst, ufp0, rn, 0, align);
531        }
532        break;
533      case 3:
534        microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>(
535                machInst, ufp0, rn, 0, align);
536        break;
537      case 4:
538        switch (eBytes) {
539          case 1:
540            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>(
541                    machInst, ufp0, rn, 0, align);
542            break;
543          case 2:
544            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>(
545                    machInst, ufp0, rn, 0, align);
546            break;
547          case 4:
548            microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>(
549                    machInst, ufp0, rn, 0, align);
550            break;
551        }
552        break;
553      case 6:
554        microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>(
555                machInst, ufp0, rn, 0, align);
556        break;
557      case 8:
558        switch (eBytes) {
559          case 2:
560            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>(
561                    machInst, ufp0, rn, 0, align);
562            break;
563          case 4:
564            microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>(
565                    machInst, ufp0, rn, 0, align);
566            break;
567        }
568        break;
569      case 12:
570        microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>(
571                machInst, ufp0, rn, 0, align);
572        break;
573      case 16:
574        microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>(
575                machInst, ufp0, rn, 0, align);
576        break;
577      default:
578        // Unrecognized load size
579        microOps[uopIdx++] = new Unknown(machInst);
580    }
581    if (wb) {
582        if (rm != 15 && rm != 13) {
583            microOps[uopIdx++] =
584                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
585        } else {
586            microOps[uopIdx++] =
587                new MicroAddiUop(machInst, rn, rn, loadSize);
588        }
589    }
590    switch (elems) {
591      case 4:
592        assert(regs == 4);
593        switch (size) {
594          case 0:
595            if (all) {
596                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>(
597                        machInst, vd * 2, ufp0, inc * 2);
598            } else {
599                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>(
600                        machInst, vd * 2, ufp0, inc * 2, lane);
601            }
602            break;
603          case 1:
604            if (all) {
605                microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>(
606                        machInst, vd * 2, ufp0, inc * 2);
607            } else {
608                microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>(
609                        machInst, vd * 2, ufp0, inc * 2, lane);
610            }
611            break;
612          case 2:
613            if (all) {
614                microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>(
615                        machInst, vd * 2, ufp0, inc * 2);
616            } else {
617                microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>(
618                        machInst, vd * 2, ufp0, inc * 2, lane);
619            }
620            break;
621          default:
622            // Bad size
623            microOps[uopIdx++] = new Unknown(machInst);
624            break;
625        }
626        break;
627      case 3:
628        assert(regs == 3);
629        switch (size) {
630          case 0:
631            if (all) {
632                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>(
633                        machInst, vd * 2, ufp0, inc * 2);
634            } else {
635                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>(
636                        machInst, vd * 2, ufp0, inc * 2, lane);
637            }
638            break;
639          case 1:
640            if (all) {
641                microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>(
642                        machInst, vd * 2, ufp0, inc * 2);
643            } else {
644                microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>(
645                        machInst, vd * 2, ufp0, inc * 2, lane);
646            }
647            break;
648          case 2:
649            if (all) {
650                microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>(
651                        machInst, vd * 2, ufp0, inc * 2);
652            } else {
653                microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>(
654                        machInst, vd * 2, ufp0, inc * 2, lane);
655            }
656            break;
657          default:
658            // Bad size
659            microOps[uopIdx++] = new Unknown(machInst);
660            break;
661        }
662        break;
663      case 2:
664        assert(regs == 2);
665        assert(loadRegs <= 2);
666        switch (size) {
667          case 0:
668            if (all) {
669                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>(
670                        machInst, vd * 2, ufp0, inc * 2);
671            } else {
672                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>(
673                        machInst, vd * 2, ufp0, inc * 2, lane);
674            }
675            break;
676          case 1:
677            if (all) {
678                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>(
679                        machInst, vd * 2, ufp0, inc * 2);
680            } else {
681                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>(
682                        machInst, vd * 2, ufp0, inc * 2, lane);
683            }
684            break;
685          case 2:
686            if (all) {
687                microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>(
688                        machInst, vd * 2, ufp0, inc * 2);
689            } else {
690                microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>(
691                        machInst, vd * 2, ufp0, inc * 2, lane);
692            }
693            break;
694          default:
695            // Bad size
696            microOps[uopIdx++] = new Unknown(machInst);
697            break;
698        }
699        break;
700      case 1:
701        assert(regs == 1 || (all && regs == 2));
702        assert(loadRegs <= 2);
703        for (unsigned offset = 0; offset < regs; offset++) {
704            switch (size) {
705              case 0:
706                if (all) {
707                    microOps[uopIdx++] =
708                        new MicroUnpackAllNeon2to2Uop<uint8_t>(
709                            machInst, (vd + offset) * 2, ufp0, inc * 2);
710                } else {
711                    microOps[uopIdx++] =
712                        new MicroUnpackNeon2to2Uop<uint8_t>(
713                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
714                }
715                break;
716              case 1:
717                if (all) {
718                    microOps[uopIdx++] =
719                        new MicroUnpackAllNeon2to2Uop<uint16_t>(
720                            machInst, (vd + offset) * 2, ufp0, inc * 2);
721                } else {
722                    microOps[uopIdx++] =
723                        new MicroUnpackNeon2to2Uop<uint16_t>(
724                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
725                }
726                break;
727              case 2:
728                if (all) {
729                    microOps[uopIdx++] =
730                        new MicroUnpackAllNeon2to2Uop<uint32_t>(
731                            machInst, (vd + offset) * 2, ufp0, inc * 2);
732                } else {
733                    microOps[uopIdx++] =
734                        new MicroUnpackNeon2to2Uop<uint32_t>(
735                            machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
736                }
737                break;
738              default:
739                // Bad size
740                microOps[uopIdx++] = new Unknown(machInst);
741                break;
742            }
743        }
744        break;
745      default:
746        // Bad number of elements to unpack
747        microOps[uopIdx++] = new Unknown(machInst);
748    }
749    assert(uopIdx == numMicroops);
750
751    for (unsigned i = 0; i < numMicroops - 1; i++) {
752        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
753        assert(uopPtr);
754        uopPtr->setDelayedCommit();
755    }
756    microOps[numMicroops - 1]->setLastMicroop();
757}
758
759VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
760                     unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
761                     unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
762    PredMacroOp(mnem, machInst, __opClass)
763{
764    assert(regs > 0 && regs <= 4);
765    assert(regs % elems == 0);
766
767    numMicroops = (regs > 2) ? 2 : 1;
768    bool wb = (rm != 15);
769    bool interleave = (elems > 1);
770
771    if (wb) numMicroops++;
772    if (interleave) numMicroops += (regs / elems);
773    microOps = new StaticInstPtr[numMicroops];
774
775    uint32_t noAlign = TLB::MustBeOne;
776
777    RegIndex rMid = interleave ? NumFloatV7ArchRegs : vd * 2;
778
779    unsigned uopIdx = 0;
780    if (interleave) {
781        switch (elems) {
782          case 4:
783            assert(regs == 4);
784            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>(
785                    size, machInst, rMid, vd * 2, inc * 2);
786            break;
787          case 3:
788            assert(regs == 3);
789            microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>(
790                    size, machInst, rMid, vd * 2, inc * 2);
791            break;
792          case 2:
793            assert(regs == 4 || regs == 2);
794            if (regs == 4) {
795                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
796                        size, machInst, rMid, vd * 2, inc * 2);
797                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
798                        size, machInst, rMid + 4, vd * 2 + 2, inc * 2);
799            } else {
800                microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
801                        size, machInst, rMid, vd * 2, inc * 2);
802            }
803            break;
804          default:
805            // Bad number of elements to interleave
806            microOps[uopIdx++] = new Unknown(machInst);
807        }
808    }
809    switch (regs) {
810      case 4:
811        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
812                size, machInst, rMid, rn, 0, align);
813        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
814                size, machInst, rMid + 4, rn, 16, noAlign);
815        break;
816      case 3:
817        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
818                size, machInst, rMid, rn, 0, align);
819        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
820                size, machInst, rMid + 4, rn, 16, noAlign);
821        break;
822      case 2:
823        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
824                size, machInst, rMid, rn, 0, align);
825        break;
826      case 1:
827        microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
828                size, machInst, rMid, rn, 0, align);
829        break;
830      default:
831        // Unknown number of registers
832        microOps[uopIdx++] = new Unknown(machInst);
833    }
834    if (wb) {
835        if (rm != 15 && rm != 13) {
836            microOps[uopIdx++] =
837                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
838        } else {
839            microOps[uopIdx++] =
840                new MicroAddiUop(machInst, rn, rn, regs * 8);
841        }
842    }
843    assert(uopIdx == numMicroops);
844
845    for (unsigned i = 0; i < numMicroops - 1; i++) {
846        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
847        assert(uopPtr);
848        uopPtr->setDelayedCommit();
849    }
850    microOps[numMicroops - 1]->setLastMicroop();
851}
852
853VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
854                         OpClass __opClass, bool all, unsigned elems,
855                         RegIndex rn, RegIndex vd, unsigned regs,
856                         unsigned inc, uint32_t size, uint32_t align,
857                         RegIndex rm, unsigned lane) :
858    PredMacroOp(mnem, machInst, __opClass)
859{
860    assert(!all);
861    assert(regs > 0 && regs <= 4);
862    assert(regs % elems == 0);
863
864    unsigned eBytes = (1 << size);
865    unsigned storeSize = eBytes * elems;
866    unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) /
867                         sizeof(FloatRegBits);
868
869    assert(storeRegs > 0 && storeRegs <= 4);
870
871    numMicroops = 1;
872    bool wb = (rm != 15);
873
874    if (wb) numMicroops++;
875    numMicroops += (regs / elems);
876    microOps = new StaticInstPtr[numMicroops];
877
878    RegIndex ufp0 = NumFloatV7ArchRegs;
879
880    unsigned uopIdx = 0;
881    switch (elems) {
882      case 4:
883        assert(regs == 4);
884        switch (size) {
885          case 0:
886            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>(
887                    machInst, ufp0, vd * 2, inc * 2, lane);
888            break;
889          case 1:
890            microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>(
891                    machInst, ufp0, vd * 2, inc * 2, lane);
892            break;
893          case 2:
894            microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>(
895                    machInst, ufp0, vd * 2, inc * 2, lane);
896            break;
897          default:
898            // Bad size
899            microOps[uopIdx++] = new Unknown(machInst);
900            break;
901        }
902        break;
903      case 3:
904        assert(regs == 3);
905        switch (size) {
906          case 0:
907            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>(
908                    machInst, ufp0, vd * 2, inc * 2, lane);
909            break;
910          case 1:
911            microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>(
912                    machInst, ufp0, vd * 2, inc * 2, lane);
913            break;
914          case 2:
915            microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>(
916                    machInst, ufp0, vd * 2, inc * 2, lane);
917            break;
918          default:
919            // Bad size
920            microOps[uopIdx++] = new Unknown(machInst);
921            break;
922        }
923        break;
924      case 2:
925        assert(regs == 2);
926        assert(storeRegs <= 2);
927        switch (size) {
928          case 0:
929            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>(
930                    machInst, ufp0, vd * 2, inc * 2, lane);
931            break;
932          case 1:
933            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>(
934                    machInst, ufp0, vd * 2, inc * 2, lane);
935            break;
936          case 2:
937            microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>(
938                    machInst, ufp0, vd * 2, inc * 2, lane);
939            break;
940          default:
941            // Bad size
942            microOps[uopIdx++] = new Unknown(machInst);
943            break;
944        }
945        break;
946      case 1:
947        assert(regs == 1 || (all && regs == 2));
948        assert(storeRegs <= 2);
949        for (unsigned offset = 0; offset < regs; offset++) {
950            switch (size) {
951              case 0:
952                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>(
953                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
954                break;
955              case 1:
956                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>(
957                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
958                break;
959              case 2:
960                microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>(
961                        machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
962                break;
963              default:
964                // Bad size
965                microOps[uopIdx++] = new Unknown(machInst);
966                break;
967            }
968        }
969        break;
970      default:
971        // Bad number of elements to unpack
972        microOps[uopIdx++] = new Unknown(machInst);
973    }
974    switch (storeSize) {
975      case 1:
976        microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>(
977                machInst, ufp0, rn, 0, align);
978        break;
979      case 2:
980        if (eBytes == 2) {
981            microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>(
982                    machInst, ufp0, rn, 0, align);
983        } else {
984            microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>(
985                    machInst, ufp0, rn, 0, align);
986        }
987        break;
988      case 3:
989        microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>(
990                machInst, ufp0, rn, 0, align);
991        break;
992      case 4:
993        switch (eBytes) {
994          case 1:
995            microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>(
996                    machInst, ufp0, rn, 0, align);
997            break;
998          case 2:
999            microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>(
1000                    machInst, ufp0, rn, 0, align);
1001            break;
1002          case 4:
1003            microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>(
1004                    machInst, ufp0, rn, 0, align);
1005            break;
1006        }
1007        break;
1008      case 6:
1009        microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>(
1010                machInst, ufp0, rn, 0, align);
1011        break;
1012      case 8:
1013        switch (eBytes) {
1014          case 2:
1015            microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>(
1016                    machInst, ufp0, rn, 0, align);
1017            break;
1018          case 4:
1019            microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>(
1020                    machInst, ufp0, rn, 0, align);
1021            break;
1022        }
1023        break;
1024      case 12:
1025        microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>(
1026                machInst, ufp0, rn, 0, align);
1027        break;
1028      case 16:
1029        microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>(
1030                machInst, ufp0, rn, 0, align);
1031        break;
1032      default:
1033        // Bad store size
1034        microOps[uopIdx++] = new Unknown(machInst);
1035    }
1036    if (wb) {
1037        if (rm != 15 && rm != 13) {
1038            microOps[uopIdx++] =
1039                new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
1040        } else {
1041            microOps[uopIdx++] =
1042                new MicroAddiUop(machInst, rn, rn, storeSize);
1043        }
1044    }
1045    assert(uopIdx == numMicroops);
1046
1047    for (unsigned i = 0; i < numMicroops - 1; i++) {
1048        MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
1049        assert(uopPtr);
1050        uopPtr->setDelayedCommit();
1051    }
1052    microOps[numMicroops - 1]->setLastMicroop();
1053}
1054
1055VldMultOp64::VldMultOp64(const char *mnem, ExtMachInst machInst,
1056                         OpClass __opClass, RegIndex rn, RegIndex vd,
1057                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
1058                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
1059    PredMacroOp(mnem, machInst, __opClass)
1060{
1061    RegIndex vx = NumFloatV8ArchRegs / 4;
1062    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
1063    bool baseIsSP = isSP((IntRegIndex) rnsp);
1064
1065    numMicroops = wb ? 1 : 0;
1066
1067    int totNumBytes = numRegs * dataSize / 8;
1068    assert(totNumBytes <= 64);
1069
1070    // The guiding principle here is that no more than 16 bytes can be
1071    // transferred at a time
1072    int numMemMicroops = totNumBytes / 16;
1073    int residuum = totNumBytes % 16;
1074    if (residuum)
1075        ++numMemMicroops;
1076    numMicroops += numMemMicroops;
1077
1078    int numMarshalMicroops = numRegs / 2 + (numRegs % 2 ? 1 : 0);
1079    numMicroops += numMarshalMicroops;
1080
1081    microOps = new StaticInstPtr[numMicroops];
1082    unsigned uopIdx = 0;
1083    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
1084        TLB::AllowUnaligned;
1085
1086    int i = 0;
1087    for(; i < numMemMicroops - 1; ++i) {
1088        microOps[uopIdx++] = new MicroNeonLoad64(
1089            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
1090            baseIsSP, 16 /* accSize */, eSize);
1091    }
1092    microOps[uopIdx++] =  new MicroNeonLoad64(
1093        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
1094        residuum ? residuum : 16 /* accSize */, eSize);
1095
1096    // Writeback microop: the post-increment amount is encoded in "Rm": a
1097    // 64-bit general register OR as '11111' for an immediate value equal to
1098    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
1099    if (wb) {
1100        if (rm != ((RegIndex) INTREG_X31)) {
1101            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
1102                                                      UXTX, 0);
1103        } else {
1104            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
1105                                                   totNumBytes);
1106        }
1107    }
1108
1109    for (int i = 0; i < numMarshalMicroops; ++i) {
1110        switch(numRegs) {
1111            case 1: microOps[uopIdx++] = new MicroDeintNeon64_1Reg(
1112                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
1113                        numStructElems, 1, i /* step */);
1114                    break;
1115            case 2: microOps[uopIdx++] = new MicroDeintNeon64_2Reg(
1116                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
1117                        numStructElems, 2, i /* step */);
1118                    break;
1119            case 3: microOps[uopIdx++] = new MicroDeintNeon64_3Reg(
1120                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
1121                        numStructElems, 3, i /* step */);
1122                    break;
1123            case 4: microOps[uopIdx++] = new MicroDeintNeon64_4Reg(
1124                        machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
1125                        numStructElems, 4, i /* step */);
1126                    break;
1127            default: panic("Invalid number of registers");
1128        }
1129
1130    }
1131
1132    assert(uopIdx == numMicroops);
1133
1134    for (int i = 0; i < numMicroops - 1; ++i) {
1135        microOps[i]->setDelayedCommit();
1136    }
1137    microOps[numMicroops - 1]->setLastMicroop();
1138}
1139
1140VstMultOp64::VstMultOp64(const char *mnem, ExtMachInst machInst,
1141                         OpClass __opClass, RegIndex rn, RegIndex vd,
1142                         RegIndex rm, uint8_t eSize, uint8_t dataSize,
1143                         uint8_t numStructElems, uint8_t numRegs, bool wb) :
1144    PredMacroOp(mnem, machInst, __opClass)
1145{
1146    RegIndex vx = NumFloatV8ArchRegs / 4;
1147    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
1148    bool baseIsSP = isSP((IntRegIndex) rnsp);
1149
1150    numMicroops = wb ? 1 : 0;
1151
1152    int totNumBytes = numRegs * dataSize / 8;
1153    assert(totNumBytes <= 64);
1154
1155    // The guiding principle here is that no more than 16 bytes can be
1156    // transferred at a time
1157    int numMemMicroops = totNumBytes / 16;
1158    int residuum = totNumBytes % 16;
1159    if (residuum)
1160        ++numMemMicroops;
1161    numMicroops += numMemMicroops;
1162
1163    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
1164    numMicroops += numMarshalMicroops;
1165
1166    microOps = new StaticInstPtr[numMicroops];
1167    unsigned uopIdx = 0;
1168
1169    for(int i = 0; i < numMarshalMicroops; ++i) {
1170        switch (numRegs) {
1171            case 1: microOps[uopIdx++] = new MicroIntNeon64_1Reg(
1172                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
1173                        numStructElems, 1, i /* step */);
1174                    break;
1175            case 2: microOps[uopIdx++] = new MicroIntNeon64_2Reg(
1176                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
1177                        numStructElems, 2, i /* step */);
1178                    break;
1179            case 3: microOps[uopIdx++] = new MicroIntNeon64_3Reg(
1180                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
1181                        numStructElems, 3, i /* step */);
1182                    break;
1183            case 4: microOps[uopIdx++] = new MicroIntNeon64_4Reg(
1184                        machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
1185                        numStructElems, 4, i /* step */);
1186                    break;
1187            default: panic("Invalid number of registers");
1188        }
1189    }
1190
1191    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
1192        TLB::AllowUnaligned;
1193
1194    int i = 0;
1195    for(; i < numMemMicroops - 1; ++i) {
1196        microOps[uopIdx++] = new MicroNeonStore64(
1197            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
1198            baseIsSP, 16 /* accSize */, eSize);
1199    }
1200    microOps[uopIdx++] = new MicroNeonStore64(
1201        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
1202        residuum ? residuum : 16 /* accSize */, eSize);
1203
1204    // Writeback microop: the post-increment amount is encoded in "Rm": a
1205    // 64-bit general register OR as '11111' for an immediate value equal to
1206    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
1207    if (wb) {
1208        if (rm != ((RegIndex) INTREG_X31)) {
1209            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
1210                                                      UXTX, 0);
1211        } else {
1212            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
1213                                                   totNumBytes);
1214        }
1215    }
1216
1217    assert(uopIdx == numMicroops);
1218
1219    for (int i = 0; i < numMicroops - 1; i++) {
1220        microOps[i]->setDelayedCommit();
1221    }
1222    microOps[numMicroops - 1]->setLastMicroop();
1223}
1224
1225VldSingleOp64::VldSingleOp64(const char *mnem, ExtMachInst machInst,
1226                             OpClass __opClass, RegIndex rn, RegIndex vd,
1227                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
1228                             uint8_t numStructElems, uint8_t index, bool wb,
1229                             bool replicate) :
1230    PredMacroOp(mnem, machInst, __opClass)
1231{
1232    RegIndex vx = NumFloatV8ArchRegs / 4;
1233    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
1234    bool baseIsSP = isSP((IntRegIndex) rnsp);
1235
1236    numMicroops = wb ? 1 : 0;
1237
1238    int eSizeBytes = 1 << eSize;
1239    int totNumBytes = numStructElems * eSizeBytes;
1240    assert(totNumBytes <= 64);
1241
1242    // The guiding principle here is that no more than 16 bytes can be
1243    // transferred at a time
1244    int numMemMicroops = totNumBytes / 16;
1245    int residuum = totNumBytes % 16;
1246    if (residuum)
1247        ++numMemMicroops;
1248    numMicroops += numMemMicroops;
1249
1250    int numMarshalMicroops = numStructElems / 2 + (numStructElems % 2 ? 1 : 0);
1251    numMicroops += numMarshalMicroops;
1252
1253    microOps = new StaticInstPtr[numMicroops];
1254    unsigned uopIdx = 0;
1255
1256    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
1257        TLB::AllowUnaligned;
1258
1259    int i = 0;
1260    for (; i < numMemMicroops - 1; ++i) {
1261        microOps[uopIdx++] = new MicroNeonLoad64(
1262            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
1263            baseIsSP, 16 /* accSize */, eSize);
1264    }
1265    microOps[uopIdx++] = new MicroNeonLoad64(
1266        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
1267        residuum ? residuum : 16 /* accSize */, eSize);
1268
1269    // Writeback microop: the post-increment amount is encoded in "Rm": a
1270    // 64-bit general register OR as '11111' for an immediate value equal to
1271    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
1272    if (wb) {
1273        if (rm != ((RegIndex) INTREG_X31)) {
1274            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
1275                                                      UXTX, 0);
1276        } else {
1277            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
1278                                                   totNumBytes);
1279        }
1280    }
1281
1282    for(int i = 0; i < numMarshalMicroops; ++i) {
1283        microOps[uopIdx++] = new MicroUnpackNeon64(
1284            machInst, vd + (RegIndex) (2 * i), vx, eSize, dataSize,
1285            numStructElems, index, i /* step */, replicate);
1286    }
1287
1288    assert(uopIdx == numMicroops);
1289
1290    for (int i = 0; i < numMicroops - 1; i++) {
1291        microOps[i]->setDelayedCommit();
1292    }
1293    microOps[numMicroops - 1]->setLastMicroop();
1294}
1295
1296VstSingleOp64::VstSingleOp64(const char *mnem, ExtMachInst machInst,
1297                             OpClass __opClass, RegIndex rn, RegIndex vd,
1298                             RegIndex rm, uint8_t eSize, uint8_t dataSize,
1299                             uint8_t numStructElems, uint8_t index, bool wb,
1300                             bool replicate) :
1301    PredMacroOp(mnem, machInst, __opClass)
1302{
1303    RegIndex vx = NumFloatV8ArchRegs / 4;
1304    RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
1305    bool baseIsSP = isSP((IntRegIndex) rnsp);
1306
1307    numMicroops = wb ? 1 : 0;
1308
1309    int eSizeBytes = 1 << eSize;
1310    int totNumBytes = numStructElems * eSizeBytes;
1311    assert(totNumBytes <= 64);
1312
1313    // The guiding principle here is that no more than 16 bytes can be
1314    // transferred at a time
1315    int numMemMicroops = totNumBytes / 16;
1316    int residuum = totNumBytes % 16;
1317    if (residuum)
1318        ++numMemMicroops;
1319    numMicroops += numMemMicroops;
1320
1321    int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
1322    numMicroops += numMarshalMicroops;
1323
1324    microOps = new StaticInstPtr[numMicroops];
1325    unsigned uopIdx = 0;
1326
1327    for(int i = 0; i < numMarshalMicroops; ++i) {
1328        microOps[uopIdx++] = new MicroPackNeon64(
1329            machInst, vx + (RegIndex) (2 * i), vd, eSize, dataSize,
1330            numStructElems, index, i /* step */, replicate);
1331    }
1332
1333    uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize |
1334        TLB::AllowUnaligned;
1335
1336    int i = 0;
1337    for(; i < numMemMicroops - 1; ++i) {
1338        microOps[uopIdx++] = new MicroNeonStore64(
1339            machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags,
1340            baseIsSP, 16 /* accsize */, eSize);
1341    }
1342    microOps[uopIdx++] = new MicroNeonStore64(
1343        machInst, vx + (RegIndex) i, rnsp, 16 * i, memaccessFlags, baseIsSP,
1344        residuum ? residuum : 16 /* accSize */, eSize);
1345
1346    // Writeback microop: the post-increment amount is encoded in "Rm": a
1347    // 64-bit general register OR as '11111' for an immediate value equal to
1348    // the total number of bytes transferred (i.e. 8, 16, 24, 32, 48 or 64)
1349    if (wb) {
1350        if (rm != ((RegIndex) INTREG_X31)) {
1351            microOps[uopIdx++] = new MicroAddXERegUop(machInst, rnsp, rnsp, rm,
1352                                                      UXTX, 0);
1353        } else {
1354            microOps[uopIdx++] = new MicroAddXiUop(machInst, rnsp, rnsp,
1355                                                   totNumBytes);
1356        }
1357    }
1358
1359    assert(uopIdx == numMicroops);
1360
1361    for (int i = 0; i < numMicroops - 1; i++) {
1362        microOps[i]->setDelayedCommit();
1363    }
1364    microOps[numMicroops - 1]->setLastMicroop();
1365}
1366
1367MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
1368                             OpClass __opClass, IntRegIndex rn,
1369                             RegIndex vd, bool single, bool up,
1370                             bool writeback, bool load, uint32_t offset) :
1371    PredMacroOp(mnem, machInst, __opClass)
1372{
1373    int i = 0;
1374
1375    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
1376    // to be functionally identical except that fldmx is deprecated. For now
1377    // we'll assume they're otherwise interchangable.
1378    int count = (single ? offset : (offset / 2));
1379    if (count == 0 || count > NumFloatV7ArchRegs)
1380        warn_once("Bad offset field for VFP load/store multiple.\n");
1381    if (count == 0) {
1382        // Force there to be at least one microop so the macroop makes sense.
1383        writeback = true;
1384    }
1385    if (count > NumFloatV7ArchRegs)
1386        count = NumFloatV7ArchRegs;
1387
1388    numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
1389    microOps = new StaticInstPtr[numMicroops];
1390
1391    int64_t addr = 0;
1392
1393    if (!up)
1394        addr = 4 * offset;
1395
1396    bool tempUp = up;
1397    for (int j = 0; j < count; j++) {
1398        if (load) {
1399            if (single) {
1400                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
1401                                                  tempUp, addr);
1402            } else {
1403                microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn,
1404                                                    tempUp, addr);
1405                microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp,
1406                                                    addr + (up ? 4 : -4));
1407            }
1408        } else {
1409            if (single) {
1410                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
1411                                                  tempUp, addr);
1412            } else {
1413                microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn,
1414                                                    tempUp, addr);
1415                microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp,
1416                                                    addr + (up ? 4 : -4));
1417            }
1418        }
1419        if (!tempUp) {
1420            addr -= (single ? 4 : 8);
1421            // The microops don't handle negative displacement, so turn if we
1422            // hit zero, flip polarity and start adding.
1423            if (addr <= 0) {
1424                tempUp = true;
1425                addr = -addr;
1426            }
1427        } else {
1428            addr += (single ? 4 : 8);
1429        }
1430    }
1431
1432    if (writeback) {
1433        if (up) {
1434            microOps[i++] =
1435                new MicroAddiUop(machInst, rn, rn, 4 * offset);
1436        } else {
1437            microOps[i++] =
1438                new MicroSubiUop(machInst, rn, rn, 4 * offset);
1439        }
1440    }
1441
1442    assert(numMicroops == i);
1443    microOps[numMicroops - 1]->setLastMicroop();
1444
1445    for (StaticInstPtr *curUop = microOps;
1446            !(*curUop)->isLastMicroop(); curUop++) {
1447        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
1448        assert(uopPtr);
1449        uopPtr->setDelayedCommit();
1450    }
1451}
1452
1453std::string
1454MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1455{
1456    std::stringstream ss;
1457    printMnemonic(ss);
1458    printReg(ss, ura);
1459    ss << ", ";
1460    printReg(ss, urb);
1461    ss << ", ";
1462    ccprintf(ss, "#%d", imm);
1463    return ss.str();
1464}
1465
1466std::string
1467MicroIntImmXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1468{
1469    std::stringstream ss;
1470    printMnemonic(ss);
1471    printReg(ss, ura);
1472    ss << ", ";
1473    printReg(ss, urb);
1474    ss << ", ";
1475    ccprintf(ss, "#%d", imm);
1476    return ss.str();
1477}
1478
1479std::string
1480MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1481{
1482    std::stringstream ss;
1483    printMnemonic(ss);
1484    ss << "[PC,CPSR]";
1485    return ss.str();
1486}
1487
1488std::string
1489MicroIntRegXOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1490{
1491    std::stringstream ss;
1492    printMnemonic(ss);
1493    printReg(ss, ura);
1494    ccprintf(ss, ", ");
1495    printReg(ss, urb);
1496    printExtendOperand(false, ss, (IntRegIndex)urc, type, shiftAmt);
1497    return ss.str();
1498}
1499
1500std::string
1501MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1502{
1503    std::stringstream ss;
1504    printMnemonic(ss);
1505    printReg(ss, ura);
1506    ss << ", ";
1507    printReg(ss, urb);
1508    return ss.str();
1509}
1510
1511std::string
1512MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1513{
1514    std::stringstream ss;
1515    printMnemonic(ss);
1516    printReg(ss, ura);
1517    ss << ", ";
1518    printReg(ss, urb);
1519    ss << ", ";
1520    printReg(ss, urc);
1521    return ss.str();
1522}
1523
1524std::string
1525MicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1526{
1527    std::stringstream ss;
1528    printMnemonic(ss);
1529    if (isFloating())
1530        printReg(ss, ura + FP_Reg_Base);
1531    else
1532        printReg(ss, ura);
1533    ss << ", [";
1534    printReg(ss, urb);
1535    ss << ", ";
1536    ccprintf(ss, "#%d", imm);
1537    ss << "]";
1538    return ss.str();
1539}
1540
1541}
1542