macromem.cc revision 7310
16145Snate@binkert.org/*
26145Snate@binkert.org * Copyright (c) 2010 ARM Limited
36145Snate@binkert.org * All rights reserved
46145Snate@binkert.org *
56145Snate@binkert.org * The license below extends only to copyright in the software and shall
66145Snate@binkert.org * not be construed as granting a license to any other intellectual
76145Snate@binkert.org * property including but not limited to intellectual property relating
86145Snate@binkert.org * to a hardware implementation of the functionality of the software
96145Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
106145Snate@binkert.org * terms below provided that you ensure that this notice is replicated
116145Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
126145Snate@binkert.org * modified or unmodified, in source code or in binary form.
136145Snate@binkert.org *
146145Snate@binkert.org * Copyright (c) 2007-2008 The Florida State University
156145Snate@binkert.org * All rights reserved.
166145Snate@binkert.org *
176145Snate@binkert.org * Redistribution and use in source and binary forms, with or without
186145Snate@binkert.org * modification, are permitted provided that the following conditions are
196145Snate@binkert.org * met: redistributions of source code must retain the above copyright
206145Snate@binkert.org * notice, this list of conditions and the following disclaimer;
216145Snate@binkert.org * redistributions in binary form must reproduce the above copyright
226145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
236145Snate@binkert.org * documentation and/or other materials provided with the distribution;
246145Snate@binkert.org * neither the name of the copyright holders nor the names of its
256145Snate@binkert.org * contributors may be used to endorse or promote products derived from
266145Snate@binkert.org * this software without specific prior written permission.
276145Snate@binkert.org *
286145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
306145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
316145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
326145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
356145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396145Snate@binkert.org *
406145Snate@binkert.org * Authors: Stephen Hines
416145Snate@binkert.org */
426145Snate@binkert.org
436145Snate@binkert.org#include "arch/arm/insts/macromem.hh"
446145Snate@binkert.org#include "arch/arm/decoder.hh"
457002Snate@binkert.org
467002Snate@binkert.orgusing namespace ArmISAInst;
477002Snate@binkert.org
488946Sandreas.hansson@arm.comnamespace ArmISA
498946Sandreas.hansson@arm.com{
507002Snate@binkert.org
517454Snate@binkert.orgMacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
527832Snate@binkert.org                       OpClass __opClass, IntRegIndex rn,
537454Snate@binkert.org                       bool index, bool up, bool user, bool writeback,
547454Snate@binkert.org                       bool load, uint32_t reglist) :
557056Snate@binkert.org    PredMacroOp(mnem, machInst, __opClass)
567048Snate@binkert.org{
578229Snate@binkert.org    uint32_t regs = reglist;
587048Snate@binkert.org    uint32_t ones = number_of_ones(reglist);
597048Snate@binkert.org    // Remember that writeback adds a uop
606154Snate@binkert.org    numMicroops = ones + (writeback ? 1 : 0) + 1;
616154Snate@binkert.org    microOps = new StaticInstPtr[numMicroops];
626876Ssteve.reinhardt@amd.com    uint32_t addr = 0;
637055Snate@binkert.org
647454Snate@binkert.org    if (!up)
657055Snate@binkert.org        addr = (ones << 2) - 4;
666145Snate@binkert.org
676145Snate@binkert.org    if (!index)
686145Snate@binkert.org        addr += 4;
696876Ssteve.reinhardt@amd.com
709171Snilay@cs.wisc.edu    StaticInstPtr *uop = microOps;
716145Snate@binkert.org    StaticInstPtr wbUop;
727048Snate@binkert.org    if (writeback) {
737048Snate@binkert.org        if (up) {
746285Snate@binkert.org            wbUop = new MicroAddiUop(machInst, rn, rn, ones * 4);
757048Snate@binkert.org        } else {
767048Snate@binkert.org            wbUop = new MicroSubiUop(machInst, rn, rn, ones * 4);
777048Snate@binkert.org        }
786145Snate@binkert.org    }
797048Snate@binkert.org
807048Snate@binkert.org    // Add 0 to Rn and stick it in ureg0.
816876Ssteve.reinhardt@amd.com    // This is equivalent to a move.
827048Snate@binkert.org    *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
836896SBrad.Beckmann@amd.com
847048Snate@binkert.org    // Write back at the start for loads. This covers the ldm exception return
857048Snate@binkert.org    // case where the base needs to be written in the old mode. Stores may need
866285Snate@binkert.org    // the original value of the base, but they don't change mode and can
877048Snate@binkert.org    // write back at the end like before.
887048Snate@binkert.org    if (load && writeback) {
897048Snate@binkert.org        *++uop = wbUop;
906285Snate@binkert.org    }
917048Snate@binkert.org
927048Snate@binkert.org    unsigned reg = 0;
937048Snate@binkert.org    bool force_user = user & !bits(reglist, 15);
947048Snate@binkert.org    bool exception_ret = user & bits(reglist, 15);
957048Snate@binkert.org
968436SBrad.Beckmann@amd.com    for (int i = 0; i < ones; i++) {
978436SBrad.Beckmann@amd.com        // Find the next register.
986285Snate@binkert.org        while (!bits(regs, reg))
996285Snate@binkert.org            reg++;
1006889SBrad.Beckmann@amd.com        replaceBits(regs, reg, 0);
1016889SBrad.Beckmann@amd.com
1027048Snate@binkert.org        unsigned regIdx = reg;
1037048Snate@binkert.org        if (force_user) {
1047048Snate@binkert.org            regIdx = intRegInMode(MODE_USER, regIdx);
1056889SBrad.Beckmann@amd.com        }
1066889SBrad.Beckmann@amd.com
1077048Snate@binkert.org        if (load) {
1087048Snate@binkert.org            if (reg == INTREG_PC && exception_ret) {
1096145Snate@binkert.org                // This must be the exception return form of ldm.
1107048Snate@binkert.org                *++uop = new MicroLdrRetUop(machInst, regIdx,
1116145Snate@binkert.org                                           INTREG_UREG0, up, addr);
1129231Snilay@cs.wisc.edu            } else {
1136145Snate@binkert.org                *++uop = new MicroLdrUop(machInst, regIdx,
1147048Snate@binkert.org                                        INTREG_UREG0, up, addr);
1157048Snate@binkert.org            }
1169171Snilay@cs.wisc.edu        } else {
1177048Snate@binkert.org            *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
1187048Snate@binkert.org        }
1196145Snate@binkert.org
1207048Snate@binkert.org        if (up)
1216889SBrad.Beckmann@amd.com            addr += 4;
1229171Snilay@cs.wisc.edu        else
1237048Snate@binkert.org            addr -= 4;
1247048Snate@binkert.org    }
1256889SBrad.Beckmann@amd.com
1267048Snate@binkert.org    if (!load && writeback) {
1277054Snate@binkert.org        *++uop = wbUop;
1287048Snate@binkert.org    }
1297048Snate@binkert.org
1306889SBrad.Beckmann@amd.com    (*uop)->setLastMicroop();
1316145Snate@binkert.org}
1326145Snate@binkert.org
1336145Snate@binkert.orgMacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
1346145Snate@binkert.org                             OpClass __opClass, IntRegIndex rn,
1357048Snate@binkert.org                             RegIndex vd, bool single, bool up,
1367048Snate@binkert.org                             bool writeback, bool load, uint32_t offset) :
1376145Snate@binkert.org    PredMacroOp(mnem, machInst, __opClass)
1386145Snate@binkert.org{
1397048Snate@binkert.org    const int maxMicroops = 17;
1409206Snilay@cs.wisc.edu    microOps = new StaticInstPtr[maxMicroops];
1417048Snate@binkert.org    int i = 0;
1427048Snate@binkert.org
1437048Snate@binkert.org    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
1447048Snate@binkert.org    // to be functionally identical except that fldmx is deprecated. For now
1457048Snate@binkert.org    // we'll assume they're otherwise interchangable.
1467048Snate@binkert.org    int count = (single ? offset : (offset / 2));
1477048Snate@binkert.org    if (count == 0 || count > NumFloatArchRegs)
1487048Snate@binkert.org        warn_once("Bad offset field for VFP load/store multiple.\n");
1497048Snate@binkert.org    if (count == 0) {
1507048Snate@binkert.org        // Force there to be at least one microop so the macroop makes sense.
1516145Snate@binkert.org        writeback = true;
1526145Snate@binkert.org    }
1537048Snate@binkert.org    if (count > NumFloatArchRegs)
1549206Snilay@cs.wisc.edu        count = NumFloatArchRegs;
1557048Snate@binkert.org
1567048Snate@binkert.org    uint32_t addr = 0;
1577048Snate@binkert.org
1589231Snilay@cs.wisc.edu    if (up)
1597048Snate@binkert.org        addr = -4 * offset;
1607054Snate@binkert.org
1617048Snate@binkert.org    for (int j = 0; j < count; j++) {
1627048Snate@binkert.org        if (load) {
1637048Snate@binkert.org            microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
1649206Snilay@cs.wisc.edu                                              true, addr);
1657048Snate@binkert.org            if (!single)
1667048Snate@binkert.org                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
1677048Snate@binkert.org                                                  true, addr + 4);
1687048Snate@binkert.org        } else {
1697048Snate@binkert.org            microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
1707048Snate@binkert.org                                              true, addr);
1717048Snate@binkert.org            if (!single)
1727048Snate@binkert.org                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
1737048Snate@binkert.org                                                  true, addr + 4);
1747048Snate@binkert.org        }
1757048Snate@binkert.org        addr += (single ? 4 : 8);
1767048Snate@binkert.org    }
1777048Snate@binkert.org
1787048Snate@binkert.org    if (writeback) {
1797048Snate@binkert.org        if (up) {
1807048Snate@binkert.org            microOps[i++] =
1817048Snate@binkert.org                new MicroAddiUop(machInst, rn, rn, 4 * offset);
1827048Snate@binkert.org        } else {
1837048Snate@binkert.org            microOps[i++] =
1847048Snate@binkert.org                new MicroSubiUop(machInst, rn, rn, 4 * offset);
1857048Snate@binkert.org        }
1867048Snate@binkert.org    }
1877048Snate@binkert.org
1889171Snilay@cs.wisc.edu    numMicroops = i;
1897048Snate@binkert.org    assert(numMicroops <= maxMicroops);
1907048Snate@binkert.org    microOps[numMicroops - 1]->setLastMicroop();
1917048Snate@binkert.org}
1927048Snate@binkert.org
1937048Snate@binkert.org}
1947048Snate@binkert.org