1/*
2 * Copyright (c) 2011-2013,2017 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: Gabe Black
38 */
39#ifndef __ARCH_ARM_MEM64_HH__
40#define __ARCH_ARM_MEM64_HH__
41
42#include "arch/arm/insts/misc64.hh"
43#include "arch/arm/insts/static_inst.hh"
44
45namespace ArmISA
46{
47
48class SysDC64 : public MiscRegOp64
49{
50  protected:
51    IntRegIndex base;
52    MiscRegIndex dest;
53    uint64_t imm;
54
55    SysDC64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
56            IntRegIndex _base, MiscRegIndex _dest, uint64_t _imm)
57        : MiscRegOp64(mnem, _machInst, __opClass, false),
58          base(_base), dest(_dest), imm(_imm)
59    {}
60
61    std::string generateDisassembly(
62            Addr pc, const SymbolTable *symtab) const override;
63};
64
65class MightBeMicro64 : public ArmStaticInst
66{
67  protected:
68    MightBeMicro64(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
69        : ArmStaticInst(mnem, _machInst, __opClass)
70    {}
71
72    void
73    advancePC(PCState &pcState) const
74    {
75        if (flags[IsLastMicroop]) {
76            pcState.uEnd();
77        } else if (flags[IsMicroop]) {
78            pcState.uAdvance();
79        } else {
80            pcState.advance();
81        }
82    }
83};
84
85class Memory64 : public MightBeMicro64
86{
87  public:
88    enum AddrMode {
89        AddrMd_Offset,
90        AddrMd_PreIndex,
91        AddrMd_PostIndex
92    };
93
94  protected:
95
96    IntRegIndex dest;
97    IntRegIndex base;
98    /// True if the base register is SP (used for SP alignment checking).
99    bool baseIsSP;
100    static const unsigned numMicroops = 3;
101
102    StaticInstPtr *uops;
103
104    Memory64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
105             IntRegIndex _dest, IntRegIndex _base)
106        : MightBeMicro64(mnem, _machInst, __opClass),
107          dest(_dest), base(_base), uops(NULL), memAccessFlags(0)
108    {
109        baseIsSP = isSP(_base);
110    }
111
112    virtual
113    ~Memory64()
114    {
115        delete [] uops;
116    }
117
118    StaticInstPtr
119    fetchMicroop(MicroPC microPC) const override
120    {
121        assert(uops != NULL && microPC < numMicroops);
122        return uops[microPC];
123    }
124
125    void startDisassembly(std::ostream &os) const;
126
127    unsigned memAccessFlags;
128
129    void setExcAcRel(bool exclusive, bool acrel);
130};
131
132class MemoryImm64 : public Memory64
133{
134  protected:
135    int64_t imm;
136
137    MemoryImm64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
138                IntRegIndex _dest, IntRegIndex _base, int64_t _imm)
139        : Memory64(mnem, _machInst, __opClass, _dest, _base), imm(_imm)
140    {}
141
142    std::string generateDisassembly(
143            Addr pc, const SymbolTable *symtab) const override;
144};
145
146class MemoryDImm64 : public MemoryImm64
147{
148  protected:
149    IntRegIndex dest2;
150
151    MemoryDImm64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
152                IntRegIndex _dest, IntRegIndex _dest2, IntRegIndex _base,
153                int64_t _imm)
154        : MemoryImm64(mnem, _machInst, __opClass, _dest, _base, _imm),
155          dest2(_dest2)
156    {}
157
158    std::string generateDisassembly(
159            Addr pc, const SymbolTable *symtab) const override;
160};
161
162class MemoryDImmEx64 : public MemoryDImm64
163{
164  protected:
165    IntRegIndex result;
166
167    MemoryDImmEx64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
168                 IntRegIndex _result, IntRegIndex _dest, IntRegIndex _dest2,
169                 IntRegIndex _base, int32_t _imm)
170        : MemoryDImm64(mnem, _machInst, __opClass, _dest, _dest2,
171                     _base, _imm), result(_result)
172    {}
173
174    std::string generateDisassembly(
175            Addr pc, const SymbolTable *symtab) const override;
176};
177
178class MemoryPreIndex64 : public MemoryImm64
179{
180  protected:
181    MemoryPreIndex64(const char *mnem, ExtMachInst _machInst,
182                     OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
183                     int64_t _imm)
184        : MemoryImm64(mnem, _machInst, __opClass, _dest, _base, _imm)
185    {}
186
187    std::string generateDisassembly(
188            Addr pc, const SymbolTable *symtab) const override;
189};
190
191class MemoryPostIndex64 : public MemoryImm64
192{
193  protected:
194    MemoryPostIndex64(const char *mnem, ExtMachInst _machInst,
195                      OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
196                      int64_t _imm)
197        : MemoryImm64(mnem, _machInst, __opClass, _dest, _base, _imm)
198    {}
199
200    std::string generateDisassembly(
201            Addr pc, const SymbolTable *symtab) const override;
202};
203
204class MemoryReg64 : public Memory64
205{
206  protected:
207    IntRegIndex offset;
208    ArmExtendType type;
209    uint64_t shiftAmt;
210
211    MemoryReg64(const char *mnem, ExtMachInst _machInst,
212                OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
213                IntRegIndex _offset, ArmExtendType _type,
214                uint64_t _shiftAmt)
215        : Memory64(mnem, _machInst, __opClass, _dest, _base),
216          offset(_offset), type(_type), shiftAmt(_shiftAmt)
217    {}
218
219    std::string generateDisassembly(
220            Addr pc, const SymbolTable *symtab) const override;
221};
222
223class MemoryRaw64 : public Memory64
224{
225  protected:
226    MemoryRaw64(const char *mnem, ExtMachInst _machInst,
227                OpClass __opClass, IntRegIndex _dest, IntRegIndex _base)
228        : Memory64(mnem, _machInst, __opClass, _dest, _base)
229    {}
230
231    std::string generateDisassembly(
232            Addr pc, const SymbolTable *symtab) const override;
233};
234
235class MemoryEx64 : public Memory64
236{
237  protected:
238    IntRegIndex result;
239
240    MemoryEx64(const char *mnem, ExtMachInst _machInst,
241               OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
242               IntRegIndex _result)
243        : Memory64(mnem, _machInst, __opClass, _dest, _base), result(_result)
244    {}
245
246    std::string generateDisassembly(
247            Addr pc, const SymbolTable *symtab) const override;
248};
249
250class MemoryLiteral64 : public Memory64
251{
252  protected:
253    int64_t imm;
254
255    MemoryLiteral64(const char *mnem, ExtMachInst _machInst,
256                    OpClass __opClass, IntRegIndex _dest, int64_t _imm)
257        : Memory64(mnem, _machInst, __opClass, _dest, INTREG_ZERO), imm(_imm)
258    {}
259
260    std::string generateDisassembly(
261            Addr pc, const SymbolTable *symtab) const override;
262};
263
264/**
265 * A generic atomic op class
266 */
267
268template<typename T>
269class AtomicGeneric2Op : public TypedAtomicOpFunctor<T>
270{
271  public:
272    AtomicGeneric2Op(T _a, std::function<void(T*,T)> _op)
273        : a(_a), op(_op)
274    {}
275    AtomicOpFunctor* clone() override
276    {
277        return new AtomicGeneric2Op<T>(*this);
278    }
279    void execute(T *b) override
280    {
281        op(b, a);
282    }
283  private:
284    T a;
285    std::function<void(T*,T)> op;
286 };
287
288template<typename T>
289class AtomicGeneric3Op : public TypedAtomicOpFunctor<T>
290{
291  public:
292    AtomicGeneric3Op(T _a, T _c, std::function<void(T*, T, T)> _op)
293        : a(_a), c(_c), op(_op)
294    {}
295    AtomicOpFunctor* clone() override
296    {
297        return new AtomicGeneric3Op<T>(*this);
298    }
299    void execute(T *b) override
300    {
301        op(b, a, c);
302    }
303  private:
304    T a;
305    T c;
306    std::function<void(T*, T, T)> op;
307};
308
309template<typename T>
310class AtomicGenericPair3Op : public TypedAtomicOpFunctor<T>
311{
312  public:
313    AtomicGenericPair3Op(std::array<T, 2>& _a, std::array<T, 2> _c,
314           std::function<void(T*, std::array<T, 2>&, std::array<T, 2>)> _op)
315        : a(_a), c(_c), op(_op)
316    {}
317    AtomicOpFunctor* clone() override
318    {
319        return new AtomicGenericPair3Op<T>(*this);
320    }
321    void execute(T* b) override
322    {
323        op(b, a, c);
324    }
325  private:
326    std::array<T, 2> a;
327    std::array<T, 2> c;
328    std::function<void(T*, std::array<T, 2>&, std::array<T, 2>)> op;
329};
330
331}
332
333#endif //__ARCH_ARM_INSTS_MEM_HH__
334