macromem.cc revision 7395
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 1647395Sgblack@eecs.umich.edu int64_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) 1757395Sgblack@eecs.umich.edu microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn, tempUp, 1767395Sgblack@eecs.umich.edu addr + (up ? 4 : -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) 1817395Sgblack@eecs.umich.edu microOps[i++] = new MicroStrFpUop(machInst, vd++, rn, tempUp, 1827395Sgblack@eecs.umich.edu addr + (up ? 4 : -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. 1887395Sgblack@eecs.umich.edu if (addr <= 0) { 1897342Sgblack@eecs.umich.edu tempUp = true; 1907395Sgblack@eecs.umich.edu addr = -addr; 1917342Sgblack@eecs.umich.edu } 1927342Sgblack@eecs.umich.edu } else { 1937342Sgblack@eecs.umich.edu addr += (single ? 4 : 8); 1947342Sgblack@eecs.umich.edu } 1957175Sgblack@eecs.umich.edu } 1967175Sgblack@eecs.umich.edu 1977175Sgblack@eecs.umich.edu if (writeback) { 1987175Sgblack@eecs.umich.edu if (up) { 1997175Sgblack@eecs.umich.edu microOps[i++] = 2007175Sgblack@eecs.umich.edu new MicroAddiUop(machInst, rn, rn, 4 * offset); 2017175Sgblack@eecs.umich.edu } else { 2027175Sgblack@eecs.umich.edu microOps[i++] = 2037175Sgblack@eecs.umich.edu new MicroSubiUop(machInst, rn, rn, 4 * offset); 2047175Sgblack@eecs.umich.edu } 2057175Sgblack@eecs.umich.edu } 2067175Sgblack@eecs.umich.edu 2077342Sgblack@eecs.umich.edu assert(numMicroops == i); 2087175Sgblack@eecs.umich.edu microOps[numMicroops - 1]->setLastMicroop(); 2097343Sgblack@eecs.umich.edu 2107343Sgblack@eecs.umich.edu for (StaticInstPtr *curUop = microOps; 2117343Sgblack@eecs.umich.edu !(*curUop)->isLastMicroop(); curUop++) { 2127343Sgblack@eecs.umich.edu MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get()); 2137343Sgblack@eecs.umich.edu assert(uopPtr); 2147343Sgblack@eecs.umich.edu uopPtr->setDelayedCommit(); 2157343Sgblack@eecs.umich.edu } 2167170Sgblack@eecs.umich.edu} 2177175Sgblack@eecs.umich.edu 2187175Sgblack@eecs.umich.edu} 219