sve_macromem.hh revision 14028:44edf7dbe672
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