sve_macromem.hh (14028:44edf7dbe672) sve_macromem.hh (14091:090449e74135)
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__