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,
| 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>
| 49 template <typename, typename> class MicroopType, 50 template <typename> class FirstFaultWritebackMicroopType>
|
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,
| 51class SveIndexedMemVI : public PredMacroOp 52{ 53 protected: 54 IntRegIndex dest; 55 IntRegIndex gp; 56 IntRegIndex base; 57 uint64_t imm; 58 59 public: 60 SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass, 61 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
|
61 uint64_t _imm)
| 62 uint64_t _imm, bool firstFault)
|
62 : PredMacroOp(mnem, machInst, __opClass), 63 dest(_dest), gp(_gp), base(_base), imm(_imm) 64 { 65 bool isLoad = (__opClass == MemReadOp);
| 63 : PredMacroOp(mnem, machInst, __opClass), 64 dest(_dest), gp(_gp), base(_base), imm(_imm) 65 { 66 bool isLoad = (__opClass == MemReadOp);
|
| 67 assert(!firstFault || isLoad);
|
66 67 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType); 68 69 numMicroops = num_elems; 70 if (isLoad) {
| 68 69 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType); 70 71 numMicroops = num_elems; 72 if (isLoad) {
|
71 numMicroops++;
| 73 if (firstFault) { 74 numMicroops += 2; 75 } else { 76 numMicroops++; 77 }
|
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,
| 78 } 79 80 microOps = new StaticInstPtr[numMicroops]; 81 82 StaticInstPtr *uop = microOps; 83 84 if (isLoad) { 85 // The first microop of a gather load copies the source vector 86 // register used for address calculation to an auxiliary register, 87 // with all subsequent microops reading from the latter. This is 88 // needed to properly handle cases where the source vector 89 // register is the same as the destination register 90 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop( 91 mnem, machInst, _base, this); 92 uop++; 93 } 94 95 for (int i = 0; i < num_elems; i++, uop++) { 96 *uop = new MicroopType<RegElemType, MemElemType>( 97 mnem, machInst, __opClass, _dest, _gp, 98 isLoad ? (IntRegIndex) VECREG_UREG0 : _base, _imm, i,
|
93 num_elems);
| 99 num_elems, firstFault);
|
94 } 95
| 100 } 101
|
96 --uop;
| 102 if (firstFault) { 103 *uop = new FirstFaultWritebackMicroopType<RegElemType>( 104 mnem, machInst, __opClass, num_elems, this); 105 } else { 106 --uop; 107 } 108
|
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,
| 109 (*uop)->setLastMicroop(); 110 microOps[0]->setFirstMicroop(); 111 112 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 113 (*uop)->setDelayedCommit(); 114 } 115 } 116 117 Fault 118 execute(ExecContext *, Trace::InstRecord *) const 119 { 120 panic("Execute method called when it shouldn't!"); 121 return NoFault; 122 } 123 124 std::string 125 generateDisassembly(Addr pc, const SymbolTable *symtab) const 126 { 127 // TODO: add suffix to transfer and base registers 128 std::stringstream ss; 129 printMnemonic(ss, "", false); 130 ccprintf(ss, "{"); 131 printVecReg(ss, dest, true); 132 ccprintf(ss, "}, "); 133 printVecPredReg(ss, gp); 134 ccprintf(ss, "/z, ["); 135 printVecReg(ss, base, true); 136 if (imm != 0) { 137 ccprintf(ss, ", #%d", imm * sizeof(MemElemType)); 138 } 139 ccprintf(ss, "]"); 140 return ss.str(); 141 } 142}; 143 144template <typename RegElemType, typename MemElemType,
|
133 template <typename, typename> class MicroopType>
| 145 template <typename, typename> class MicroopType, 146 template <typename> class FirstFaultWritebackMicroopType>
|
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,
| 147class SveIndexedMemSV : public PredMacroOp 148{ 149 protected: 150 IntRegIndex dest; 151 IntRegIndex gp; 152 IntRegIndex base; 153 IntRegIndex offset; 154 155 bool offsetIs32; 156 bool offsetIsSigned; 157 bool offsetIsScaled; 158 159 public: 160 SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass, 161 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, 162 IntRegIndex _offset, bool _offsetIs32,
|
150 bool _offsetIsSigned, bool _offsetIsScaled)
| 163 bool _offsetIsSigned, bool _offsetIsScaled, 164 bool firstFault)
|
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);
| 165 : PredMacroOp(mnem, machInst, __opClass), 166 dest(_dest), gp(_gp), base(_base), offset(_offset), 167 offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned), 168 offsetIsScaled(_offsetIsScaled) 169 { 170 bool isLoad = (__opClass == MemReadOp);
|
| 171 assert(!firstFault || isLoad);
|
157 158 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType); 159 160 numMicroops = num_elems; 161 if (isLoad) {
| 172 173 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType); 174 175 numMicroops = num_elems; 176 if (isLoad) {
|
162 numMicroops++;
| 177 if (firstFault) { 178 numMicroops += 2; 179 } else { 180 numMicroops++; 181 }
|
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,
| 182 } 183 184 microOps = new StaticInstPtr[numMicroops]; 185 186 StaticInstPtr *uop = microOps; 187 188 if (isLoad) { 189 // The first microop of a gather load copies the source vector 190 // register used for address calculation to an auxiliary register, 191 // with all subsequent microops reading from the latter. This is 192 // needed to properly handle cases where the source vector 193 // register is the same as the destination register 194 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop( 195 mnem, machInst, _offset, this); 196 uop++; 197 } 198 199 for (int i = 0; i < num_elems; i++, uop++) { 200 *uop = new MicroopType<RegElemType, MemElemType>( 201 mnem, machInst, __opClass, _dest, _gp, _base, 202 isLoad ? (IntRegIndex) VECREG_UREG0 : _offset, _offsetIs32,
|
184 _offsetIsSigned, _offsetIsScaled, i, num_elems);
| 203 _offsetIsSigned, _offsetIsScaled, i, num_elems, firstFault);
|
185 } 186
| 204 } 205
|
187 --uop;
| 206 if (firstFault) { 207 *uop = new FirstFaultWritebackMicroopType<RegElemType>( 208 mnem, machInst, __opClass, num_elems, this); 209 } else { 210 --uop; 211 } 212
|
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__
| 213 (*uop)->setLastMicroop(); 214 microOps[0]->setFirstMicroop(); 215 216 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 217 (*uop)->setDelayedCommit(); 218 } 219 } 220 221 Fault 222 execute(ExecContext *, Trace::InstRecord *) const 223 { 224 panic("Execute method called when it shouldn't!"); 225 return NoFault; 226 } 227 228 std::string 229 generateDisassembly(Addr pc, const SymbolTable *symtab) const 230 { 231 // TODO: add suffix to transfer and base registers 232 std::stringstream ss; 233 printMnemonic(ss, "", false); 234 ccprintf(ss, "{"); 235 printVecReg(ss, dest, true); 236 ccprintf(ss, "}, "); 237 printVecPredReg(ss, gp); 238 ccprintf(ss, "/z, ["); 239 printIntReg(ss, base); 240 ccprintf(ss, ", "); 241 printVecReg(ss, offset, true); 242 ccprintf(ss, "]"); 243 return ss.str(); 244 } 245}; 246 247} // namespace ArmISA 248 249#endif // __ARCH_ARM_SVE_MACROMEM_HH__
|