sve_macromem.hh revision 14028
1/* 2 * Copyright (c) 2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Giacomo Gabrielli 38 */ 39 40#ifndef __ARCH_ARM_SVE_MACROMEM_HH__ 41#define __ARCH_ARM_SVE_MACROMEM_HH__ 42 43#include "arch/arm/generated/decoder.hh" 44#include "arch/arm/insts/pred_inst.hh" 45 46namespace ArmISA { 47 48template <typename RegElemType, typename MemElemType, 49 template <typename, typename> class MicroopType> 50class SveIndexedMemVI : public PredMacroOp 51{ 52 protected: 53 IntRegIndex dest; 54 IntRegIndex gp; 55 IntRegIndex base; 56 uint64_t imm; 57 58 public: 59 SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass, 60 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, 61 uint64_t _imm) 62 : PredMacroOp(mnem, machInst, __opClass), 63 dest(_dest), gp(_gp), base(_base), imm(_imm) 64 { 65 bool isLoad = (__opClass == MemReadOp); 66 67 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType); 68 69 numMicroops = num_elems; 70 if (isLoad) { 71 numMicroops++; 72 } 73 74 microOps = new StaticInstPtr[numMicroops]; 75 76 StaticInstPtr *uop = microOps; 77 78 if (isLoad) { 79 // The first microop of a gather load copies the source vector 80 // register used for address calculation to an auxiliary register, 81 // with all subsequent microops reading from the latter. This is 82 // needed to properly handle cases where the source vector 83 // register is the same as the destination register 84 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop( 85 mnem, machInst, _base, this); 86 uop++; 87 } 88 89 for (int i = 0; i < num_elems; i++, uop++) { 90 *uop = new MicroopType<RegElemType, MemElemType>( 91 mnem, machInst, __opClass, _dest, _gp, 92 isLoad ? (IntRegIndex) VECREG_UREG0 : _base, _imm, i, 93 num_elems); 94 } 95 96 --uop; 97 (*uop)->setLastMicroop(); 98 microOps[0]->setFirstMicroop(); 99 100 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 101 (*uop)->setDelayedCommit(); 102 } 103 } 104 105 Fault 106 execute(ExecContext *, Trace::InstRecord *) const 107 { 108 panic("Execute method called when it shouldn't!"); 109 return NoFault; 110 } 111 112 std::string 113 generateDisassembly(Addr pc, const SymbolTable *symtab) const 114 { 115 // TODO: add suffix to transfer and base registers 116 std::stringstream ss; 117 printMnemonic(ss, "", false); 118 ccprintf(ss, "{"); 119 printVecReg(ss, dest, true); 120 ccprintf(ss, "}, "); 121 printVecPredReg(ss, gp); 122 ccprintf(ss, "/z, ["); 123 printVecReg(ss, base, true); 124 if (imm != 0) { 125 ccprintf(ss, ", #%d", imm * sizeof(MemElemType)); 126 } 127 ccprintf(ss, "]"); 128 return ss.str(); 129 } 130}; 131 132template <typename RegElemType, typename MemElemType, 133 template <typename, typename> class MicroopType> 134class SveIndexedMemSV : public PredMacroOp 135{ 136 protected: 137 IntRegIndex dest; 138 IntRegIndex gp; 139 IntRegIndex base; 140 IntRegIndex offset; 141 142 bool offsetIs32; 143 bool offsetIsSigned; 144 bool offsetIsScaled; 145 146 public: 147 SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass, 148 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, 149 IntRegIndex _offset, bool _offsetIs32, 150 bool _offsetIsSigned, bool _offsetIsScaled) 151 : PredMacroOp(mnem, machInst, __opClass), 152 dest(_dest), gp(_gp), base(_base), offset(_offset), 153 offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned), 154 offsetIsScaled(_offsetIsScaled) 155 { 156 bool isLoad = (__opClass == MemReadOp); 157 158 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType); 159 160 numMicroops = num_elems; 161 if (isLoad) { 162 numMicroops++; 163 } 164 165 microOps = new StaticInstPtr[numMicroops]; 166 167 StaticInstPtr *uop = microOps; 168 169 if (isLoad) { 170 // The first microop of a gather load copies the source vector 171 // register used for address calculation to an auxiliary register, 172 // with all subsequent microops reading from the latter. This is 173 // needed to properly handle cases where the source vector 174 // register is the same as the destination register 175 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop( 176 mnem, machInst, _offset, this); 177 uop++; 178 } 179 180 for (int i = 0; i < num_elems; i++, uop++) { 181 *uop = new MicroopType<RegElemType, MemElemType>( 182 mnem, machInst, __opClass, _dest, _gp, _base, 183 isLoad ? (IntRegIndex) VECREG_UREG0 : _offset, _offsetIs32, 184 _offsetIsSigned, _offsetIsScaled, i, num_elems); 185 } 186 187 --uop; 188 (*uop)->setLastMicroop(); 189 microOps[0]->setFirstMicroop(); 190 191 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 192 (*uop)->setDelayedCommit(); 193 } 194 } 195 196 Fault 197 execute(ExecContext *, Trace::InstRecord *) const 198 { 199 panic("Execute method called when it shouldn't!"); 200 return NoFault; 201 } 202 203 std::string 204 generateDisassembly(Addr pc, const SymbolTable *symtab) const 205 { 206 // TODO: add suffix to transfer and base registers 207 std::stringstream ss; 208 printMnemonic(ss, "", false); 209 ccprintf(ss, "{"); 210 printVecReg(ss, dest, true); 211 ccprintf(ss, "}, "); 212 printVecPredReg(ss, gp); 213 ccprintf(ss, "/z, ["); 214 printIntReg(ss, base); 215 ccprintf(ss, ", "); 216 printVecReg(ss, offset, true); 217 ccprintf(ss, "]"); 218 return ss.str(); 219 } 220}; 221 222} // namespace ArmISA 223 224#endif // __ARCH_ARM_SVE_MACROMEM_HH__ 225