macromem.cc revision 7343
17170Sgblack@eecs.umich.edu/*
27170Sgblack@eecs.umich.edu * Copyright (c) 2010 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
437170Sgblack@eecs.umich.edu#include "arch/arm/insts/macromem.hh"
447170Sgblack@eecs.umich.edu#include "arch/arm/decoder.hh"
457170Sgblack@eecs.umich.edu
467170Sgblack@eecs.umich.eduusing namespace ArmISAInst;
477170Sgblack@eecs.umich.edu
487170Sgblack@eecs.umich.edunamespace ArmISA
497170Sgblack@eecs.umich.edu{
507170Sgblack@eecs.umich.edu
517170Sgblack@eecs.umich.eduMacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
527170Sgblack@eecs.umich.edu                       OpClass __opClass, IntRegIndex rn,
537170Sgblack@eecs.umich.edu                       bool index, bool up, bool user, bool writeback,
547170Sgblack@eecs.umich.edu                       bool load, uint32_t reglist) :
557170Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
567170Sgblack@eecs.umich.edu{
577170Sgblack@eecs.umich.edu    uint32_t regs = reglist;
587170Sgblack@eecs.umich.edu    uint32_t ones = number_of_ones(reglist);
597170Sgblack@eecs.umich.edu    // Remember that writeback adds a uop
607170Sgblack@eecs.umich.edu    numMicroops = ones + (writeback ? 1 : 0) + 1;
617170Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
627170Sgblack@eecs.umich.edu    uint32_t addr = 0;
637170Sgblack@eecs.umich.edu
647170Sgblack@eecs.umich.edu    if (!up)
657170Sgblack@eecs.umich.edu        addr = (ones << 2) - 4;
667170Sgblack@eecs.umich.edu
677170Sgblack@eecs.umich.edu    if (!index)
687170Sgblack@eecs.umich.edu        addr += 4;
697170Sgblack@eecs.umich.edu
707190Sgblack@eecs.umich.edu    StaticInstPtr *uop = microOps;
717190Sgblack@eecs.umich.edu    StaticInstPtr wbUop;
727190Sgblack@eecs.umich.edu    if (writeback) {
737190Sgblack@eecs.umich.edu        if (up) {
747190Sgblack@eecs.umich.edu            wbUop = new MicroAddiUop(machInst, rn, rn, ones * 4);
757190Sgblack@eecs.umich.edu        } else {
767190Sgblack@eecs.umich.edu            wbUop = new MicroSubiUop(machInst, rn, rn, ones * 4);
777190Sgblack@eecs.umich.edu        }
787190Sgblack@eecs.umich.edu    }
797190Sgblack@eecs.umich.edu
807170Sgblack@eecs.umich.edu    // Add 0 to Rn and stick it in ureg0.
817170Sgblack@eecs.umich.edu    // This is equivalent to a move.
827190Sgblack@eecs.umich.edu    *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
837190Sgblack@eecs.umich.edu
847190Sgblack@eecs.umich.edu    // Write back at the start for loads. This covers the ldm exception return
857190Sgblack@eecs.umich.edu    // case where the base needs to be written in the old mode. Stores may need
867190Sgblack@eecs.umich.edu    // the original value of the base, but they don't change mode and can
877190Sgblack@eecs.umich.edu    // write back at the end like before.
887190Sgblack@eecs.umich.edu    if (load && writeback) {
897190Sgblack@eecs.umich.edu        *++uop = wbUop;
907190Sgblack@eecs.umich.edu    }
917170Sgblack@eecs.umich.edu
927170Sgblack@eecs.umich.edu    unsigned reg = 0;
937170Sgblack@eecs.umich.edu    bool force_user = user & !bits(reglist, 15);
947170Sgblack@eecs.umich.edu    bool exception_ret = user & bits(reglist, 15);
957170Sgblack@eecs.umich.edu
967190Sgblack@eecs.umich.edu    for (int i = 0; i < ones; i++) {
977170Sgblack@eecs.umich.edu        // Find the next register.
987170Sgblack@eecs.umich.edu        while (!bits(regs, reg))
997170Sgblack@eecs.umich.edu            reg++;
1007170Sgblack@eecs.umich.edu        replaceBits(regs, reg, 0);
1017170Sgblack@eecs.umich.edu
1027170Sgblack@eecs.umich.edu        unsigned regIdx = reg;
1037170Sgblack@eecs.umich.edu        if (force_user) {
1047310Sgblack@eecs.umich.edu            regIdx = intRegInMode(MODE_USER, regIdx);
1057170Sgblack@eecs.umich.edu        }
1067170Sgblack@eecs.umich.edu
1077170Sgblack@eecs.umich.edu        if (load) {
1087170Sgblack@eecs.umich.edu            if (reg == INTREG_PC && exception_ret) {
1097170Sgblack@eecs.umich.edu                // This must be the exception return form of ldm.
1107190Sgblack@eecs.umich.edu                *++uop = new MicroLdrRetUop(machInst, regIdx,
1117190Sgblack@eecs.umich.edu                                           INTREG_UREG0, up, addr);
1127170Sgblack@eecs.umich.edu            } else {
1137190Sgblack@eecs.umich.edu                *++uop = new MicroLdrUop(machInst, regIdx,
1147190Sgblack@eecs.umich.edu                                        INTREG_UREG0, up, addr);
1157170Sgblack@eecs.umich.edu            }
1167170Sgblack@eecs.umich.edu        } else {
1177190Sgblack@eecs.umich.edu            *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
1187170Sgblack@eecs.umich.edu        }
1197170Sgblack@eecs.umich.edu
1207170Sgblack@eecs.umich.edu        if (up)
1217170Sgblack@eecs.umich.edu            addr += 4;
1227170Sgblack@eecs.umich.edu        else
1237170Sgblack@eecs.umich.edu            addr -= 4;
1247170Sgblack@eecs.umich.edu    }
1257170Sgblack@eecs.umich.edu
1267190Sgblack@eecs.umich.edu    if (!load && writeback) {
1277190Sgblack@eecs.umich.edu        *++uop = wbUop;
1287170Sgblack@eecs.umich.edu    }
1297190Sgblack@eecs.umich.edu
1307190Sgblack@eecs.umich.edu    (*uop)->setLastMicroop();
1317343Sgblack@eecs.umich.edu
1327343Sgblack@eecs.umich.edu    for (StaticInstPtr *curUop = microOps;
1337343Sgblack@eecs.umich.edu            !(*curUop)->isLastMicroop(); curUop++) {
1347343Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
1357343Sgblack@eecs.umich.edu        assert(uopPtr);
1367343Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
1377343Sgblack@eecs.umich.edu    }
1387170Sgblack@eecs.umich.edu}
1397170Sgblack@eecs.umich.edu
1407175Sgblack@eecs.umich.eduMacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
1417175Sgblack@eecs.umich.edu                             OpClass __opClass, IntRegIndex rn,
1427175Sgblack@eecs.umich.edu                             RegIndex vd, bool single, bool up,
1437175Sgblack@eecs.umich.edu                             bool writeback, bool load, uint32_t offset) :
1447175Sgblack@eecs.umich.edu    PredMacroOp(mnem, machInst, __opClass)
1457175Sgblack@eecs.umich.edu{
1467175Sgblack@eecs.umich.edu    int i = 0;
1477175Sgblack@eecs.umich.edu
1487175Sgblack@eecs.umich.edu    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
1497175Sgblack@eecs.umich.edu    // to be functionally identical except that fldmx is deprecated. For now
1507175Sgblack@eecs.umich.edu    // we'll assume they're otherwise interchangable.
1517175Sgblack@eecs.umich.edu    int count = (single ? offset : (offset / 2));
1527175Sgblack@eecs.umich.edu    if (count == 0 || count > NumFloatArchRegs)
1537175Sgblack@eecs.umich.edu        warn_once("Bad offset field for VFP load/store multiple.\n");
1547175Sgblack@eecs.umich.edu    if (count == 0) {
1557175Sgblack@eecs.umich.edu        // Force there to be at least one microop so the macroop makes sense.
1567175Sgblack@eecs.umich.edu        writeback = true;
1577175Sgblack@eecs.umich.edu    }
1587175Sgblack@eecs.umich.edu    if (count > NumFloatArchRegs)
1597175Sgblack@eecs.umich.edu        count = NumFloatArchRegs;
1607175Sgblack@eecs.umich.edu
1617342Sgblack@eecs.umich.edu    numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
1627342Sgblack@eecs.umich.edu    microOps = new StaticInstPtr[numMicroops];
1637342Sgblack@eecs.umich.edu
1647175Sgblack@eecs.umich.edu    uint32_t addr = 0;
1657175Sgblack@eecs.umich.edu
1667342Sgblack@eecs.umich.edu    if (!up)
1677342Sgblack@eecs.umich.edu        addr = 4 * offset;
1687175Sgblack@eecs.umich.edu
1697342Sgblack@eecs.umich.edu    bool tempUp = up;
1707175Sgblack@eecs.umich.edu    for (int j = 0; j < count; j++) {
1717175Sgblack@eecs.umich.edu        if (load) {
1727175Sgblack@eecs.umich.edu            microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
1737342Sgblack@eecs.umich.edu                                              tempUp, addr);
1747175Sgblack@eecs.umich.edu            if (!single)
1757175Sgblack@eecs.umich.edu                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
1767342Sgblack@eecs.umich.edu                                                  tempUp, addr + 4);
1777175Sgblack@eecs.umich.edu        } else {
1787175Sgblack@eecs.umich.edu            microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
1797342Sgblack@eecs.umich.edu                                              tempUp, addr);
1807175Sgblack@eecs.umich.edu            if (!single)
1817175Sgblack@eecs.umich.edu                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
1827342Sgblack@eecs.umich.edu                                                  tempUp, addr + 4);
1837175Sgblack@eecs.umich.edu        }
1847342Sgblack@eecs.umich.edu        if (!tempUp) {
1857342Sgblack@eecs.umich.edu            addr -= (single ? 4 : 8);
1867342Sgblack@eecs.umich.edu            // The microops don't handle negative displacement, so turn if we
1877342Sgblack@eecs.umich.edu            // hit zero, flip polarity and start adding.
1887342Sgblack@eecs.umich.edu            if (addr == 0) {
1897342Sgblack@eecs.umich.edu                tempUp = true;
1907342Sgblack@eecs.umich.edu            }
1917342Sgblack@eecs.umich.edu        } else {
1927342Sgblack@eecs.umich.edu            addr += (single ? 4 : 8);
1937342Sgblack@eecs.umich.edu        }
1947175Sgblack@eecs.umich.edu    }
1957175Sgblack@eecs.umich.edu
1967175Sgblack@eecs.umich.edu    if (writeback) {
1977175Sgblack@eecs.umich.edu        if (up) {
1987175Sgblack@eecs.umich.edu            microOps[i++] =
1997175Sgblack@eecs.umich.edu                new MicroAddiUop(machInst, rn, rn, 4 * offset);
2007175Sgblack@eecs.umich.edu        } else {
2017175Sgblack@eecs.umich.edu            microOps[i++] =
2027175Sgblack@eecs.umich.edu                new MicroSubiUop(machInst, rn, rn, 4 * offset);
2037175Sgblack@eecs.umich.edu        }
2047175Sgblack@eecs.umich.edu    }
2057175Sgblack@eecs.umich.edu
2067342Sgblack@eecs.umich.edu    assert(numMicroops == i);
2077175Sgblack@eecs.umich.edu    microOps[numMicroops - 1]->setLastMicroop();
2087343Sgblack@eecs.umich.edu
2097343Sgblack@eecs.umich.edu    for (StaticInstPtr *curUop = microOps;
2107343Sgblack@eecs.umich.edu            !(*curUop)->isLastMicroop(); curUop++) {
2117343Sgblack@eecs.umich.edu        MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
2127343Sgblack@eecs.umich.edu        assert(uopPtr);
2137343Sgblack@eecs.umich.edu        uopPtr->setDelayedCommit();
2147343Sgblack@eecs.umich.edu    }
2157170Sgblack@eecs.umich.edu}
2167175Sgblack@eecs.umich.edu
2177175Sgblack@eecs.umich.edu}
218