1/*
2 * Copyright (c) 2010 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 * Copyright (c) 2007-2008 The Florida State University
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Stephen Hines
41 */
42#ifndef __ARCH_ARM_MEM_HH__
43#define __ARCH_ARM_MEM_HH__
44
45#include "arch/arm/insts/pred_inst.hh"
46
47namespace ArmISA
48{
49
50class MightBeMicro : public PredOp
51{
52  protected:
53    MightBeMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
54        : PredOp(mnem, _machInst, __opClass)
55    {}
56
57    void
58    advancePC(PCState &pcState) const
59    {
60        if (flags[IsLastMicroop]) {
61            pcState.uEnd();
62        } else if (flags[IsMicroop]) {
63            pcState.uAdvance();
64        } else {
65            pcState.advance();
66        }
67    }
68};
69
70// The address is a base register plus an immediate.
71class RfeOp : public MightBeMicro
72{
73  public:
74    enum AddrMode {
75        DecrementAfter,
76        DecrementBefore,
77        IncrementAfter,
78        IncrementBefore
79    };
80  protected:
81    IntRegIndex base;
82    AddrMode mode;
83    bool wb;
84    IntRegIndex ura, urb, urc;
85    static const unsigned numMicroops = 3;
86
87    StaticInstPtr *uops;
88
89    RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
90          IntRegIndex _base, AddrMode _mode, bool _wb)
91        : MightBeMicro(mnem, _machInst, __opClass),
92          base(_base), mode(_mode), wb(_wb),
93          ura(INTREG_UREG0), urb(INTREG_UREG1),
94          urc(INTREG_UREG2),
95          uops(NULL)
96    {}
97
98    virtual
99    ~RfeOp()
100    {
101        delete [] uops;
102    }
103
104    StaticInstPtr
105    fetchMicroop(MicroPC microPC) const override
106    {
107        assert(uops != NULL && microPC < numMicroops);
108        return uops[microPC];
109    }
110
111    std::string generateDisassembly(
112            Addr pc, const SymbolTable *symtab) const override;
113};
114
115// The address is a base register plus an immediate.
116class SrsOp : public MightBeMicro
117{
118  public:
119    enum AddrMode {
120        DecrementAfter,
121        DecrementBefore,
122        IncrementAfter,
123        IncrementBefore
124    };
125  protected:
126    uint32_t regMode;
127    AddrMode mode;
128    bool wb;
129    static const unsigned numMicroops = 2;
130
131    StaticInstPtr *uops;
132
133    SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
134          uint32_t _regMode, AddrMode _mode, bool _wb)
135        : MightBeMicro(mnem, _machInst, __opClass),
136          regMode(_regMode), mode(_mode), wb(_wb), uops(NULL)
137    {}
138
139    virtual
140    ~SrsOp()
141    {
142        delete [] uops;
143    }
144
145    StaticInstPtr
146    fetchMicroop(MicroPC microPC) const override
147    {
148        assert(uops != NULL && microPC < numMicroops);
149        return uops[microPC];
150    }
151
152    std::string generateDisassembly(
153            Addr pc, const SymbolTable *symtab) const override;
154};
155
156class Memory : public MightBeMicro
157{
158  public:
159    enum AddrMode {
160        AddrMd_Offset,
161        AddrMd_PreIndex,
162        AddrMd_PostIndex
163    };
164
165  protected:
166
167    IntRegIndex dest;
168    IntRegIndex base;
169    bool add;
170    static const unsigned numMicroops = 3;
171
172    StaticInstPtr *uops;
173
174    Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
175           IntRegIndex _dest, IntRegIndex _base, bool _add)
176        : MightBeMicro(mnem, _machInst, __opClass),
177          dest(_dest), base(_base), add(_add), uops(NULL)
178    {}
179
180    virtual
181    ~Memory()
182    {
183        delete [] uops;
184    }
185
186    StaticInstPtr
187    fetchMicroop(MicroPC microPC) const override
188    {
189        assert(uops != NULL && microPC < numMicroops);
190        return uops[microPC];
191    }
192
193    virtual void
194    printOffset(std::ostream &os) const
195    {}
196
197    virtual void
198    printDest(std::ostream &os) const
199    {
200        printIntReg(os, dest);
201    }
202
203    void printInst(std::ostream &os, AddrMode addrMode) const;
204};
205
206// The address is a base register plus an immediate.
207class MemoryImm : public Memory
208{
209  protected:
210    int32_t imm;
211
212    MemoryImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
213              IntRegIndex _dest, IntRegIndex _base, bool _add, int32_t _imm)
214        : Memory(mnem, _machInst, __opClass, _dest, _base, _add), imm(_imm)
215    {}
216
217    void
218    printOffset(std::ostream &os) const
219    {
220        int32_t pImm = imm;
221        if (!add)
222            pImm = -pImm;
223        ccprintf(os, "#%d", pImm);
224    }
225};
226
227class MemoryExImm : public MemoryImm
228{
229  protected:
230    IntRegIndex result;
231
232    MemoryExImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
233                IntRegIndex _result, IntRegIndex _dest, IntRegIndex _base,
234                bool _add, int32_t _imm)
235        : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm),
236                    result(_result)
237    {}
238
239    void
240    printDest(std::ostream &os) const
241    {
242        printIntReg(os, result);
243        os << ", ";
244        MemoryImm::printDest(os);
245    }
246};
247
248// The address is a base register plus an immediate.
249class MemoryDImm : public MemoryImm
250{
251  protected:
252    IntRegIndex dest2;
253
254    MemoryDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
255              IntRegIndex _dest, IntRegIndex _dest2,
256              IntRegIndex _base, bool _add, int32_t _imm)
257        : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm),
258          dest2(_dest2)
259    {}
260
261    void
262    printDest(std::ostream &os) const
263    {
264        MemoryImm::printDest(os);
265        os << ", ";
266        printIntReg(os, dest2);
267    }
268};
269
270class MemoryExDImm : public MemoryDImm
271{
272  protected:
273    IntRegIndex result;
274
275    MemoryExDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
276                 IntRegIndex _result, IntRegIndex _dest, IntRegIndex _dest2,
277                 IntRegIndex _base, bool _add, int32_t _imm)
278        : MemoryDImm(mnem, _machInst, __opClass, _dest, _dest2,
279                     _base, _add, _imm), result(_result)
280    {}
281
282    void
283    printDest(std::ostream &os) const
284    {
285        printIntReg(os, result);
286        os << ", ";
287        MemoryDImm::printDest(os);
288    }
289};
290
291// The address is a shifted register plus an immediate
292class MemoryReg : public Memory
293{
294  protected:
295    int32_t shiftAmt;
296    ArmShiftType shiftType;
297    IntRegIndex index;
298
299    MemoryReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
300              IntRegIndex _dest, IntRegIndex _base, bool _add,
301              int32_t _shiftAmt, ArmShiftType _shiftType,
302              IntRegIndex _index)
303        : Memory(mnem, _machInst, __opClass, _dest, _base, _add),
304          shiftAmt(_shiftAmt), shiftType(_shiftType), index(_index)
305    {}
306
307    void printOffset(std::ostream &os) const;
308};
309
310class MemoryDReg : public MemoryReg
311{
312  protected:
313    IntRegIndex dest2;
314
315    MemoryDReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
316               IntRegIndex _dest, IntRegIndex _dest2,
317               IntRegIndex _base, bool _add,
318               int32_t _shiftAmt, ArmShiftType _shiftType,
319               IntRegIndex _index)
320        : MemoryReg(mnem, _machInst, __opClass, _dest, _base, _add,
321                    _shiftAmt, _shiftType, _index),
322          dest2(_dest2)
323    {}
324
325    void
326    printDest(std::ostream &os) const
327    {
328        MemoryReg::printDest(os);
329        os << ", ";
330        printIntReg(os, dest2);
331    }
332};
333
334template<class Base>
335class MemoryOffset : public Base
336{
337  protected:
338    MemoryOffset(const char *mnem, ExtMachInst _machInst,
339                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
340                 bool _add, int32_t _imm)
341        : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm)
342    {}
343
344    MemoryOffset(const char *mnem, ExtMachInst _machInst,
345                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
346                 bool _add, int32_t _shiftAmt, ArmShiftType _shiftType,
347                 IntRegIndex _index)
348        : Base(mnem, _machInst, __opClass, _dest, _base, _add,
349                _shiftAmt, _shiftType, _index)
350    {}
351
352    MemoryOffset(const char *mnem, ExtMachInst _machInst,
353                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
354                 IntRegIndex _base, bool _add, int32_t _imm)
355        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
356    {}
357
358    MemoryOffset(const char *mnem, ExtMachInst _machInst,
359                 OpClass __opClass, IntRegIndex _result,
360                 IntRegIndex _dest, IntRegIndex _dest2,
361                 IntRegIndex _base, bool _add, int32_t _imm)
362        : Base(mnem, _machInst, __opClass, _result,
363                _dest, _dest2, _base, _add, _imm)
364    {}
365
366    MemoryOffset(const char *mnem, ExtMachInst _machInst,
367                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
368                 IntRegIndex _base, bool _add,
369                 int32_t _shiftAmt, ArmShiftType _shiftType,
370                 IntRegIndex _index)
371        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add,
372                _shiftAmt, _shiftType, _index)
373    {}
374
375    std::string
376    generateDisassembly(Addr pc, const SymbolTable *symtab) const
377    {
378        std::stringstream ss;
379        this->printInst(ss, Memory::AddrMd_Offset);
380        return ss.str();
381    }
382};
383
384template<class Base>
385class MemoryPreIndex : public Base
386{
387  protected:
388    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
389                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
390                   bool _add, int32_t _imm)
391        : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm)
392    {}
393
394    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
395                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
396                   bool _add, int32_t _shiftAmt, ArmShiftType _shiftType,
397                   IntRegIndex _index)
398        : Base(mnem, _machInst, __opClass, _dest, _base, _add,
399                _shiftAmt, _shiftType, _index)
400    {}
401
402    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
403                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
404                   IntRegIndex _base, bool _add, int32_t _imm)
405        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
406    {}
407
408    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
409                   OpClass __opClass, IntRegIndex _result,
410                   IntRegIndex _dest, IntRegIndex _dest2,
411                   IntRegIndex _base, bool _add, int32_t _imm)
412        : Base(mnem, _machInst, __opClass, _result,
413                _dest, _dest2, _base, _add, _imm)
414    {}
415
416    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
417                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
418                   IntRegIndex _base, bool _add,
419                   int32_t _shiftAmt, ArmShiftType _shiftType,
420                   IntRegIndex _index)
421        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add,
422                _shiftAmt, _shiftType, _index)
423    {}
424
425    std::string
426    generateDisassembly(Addr pc, const SymbolTable *symtab) const
427    {
428        std::stringstream ss;
429        this->printInst(ss, Memory::AddrMd_PreIndex);
430        return ss.str();
431    }
432};
433
434template<class Base>
435class MemoryPostIndex : public Base
436{
437  protected:
438    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
439                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
440                    bool _add, int32_t _imm)
441        : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm)
442    {}
443
444    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
445                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
446                    bool _add, int32_t _shiftAmt, ArmShiftType _shiftType,
447                    IntRegIndex _index)
448        : Base(mnem, _machInst, __opClass, _dest, _base, _add,
449                _shiftAmt, _shiftType, _index)
450    {}
451
452    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
453                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
454                    IntRegIndex _base, bool _add, int32_t _imm)
455        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
456    {}
457
458    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
459                    OpClass __opClass, IntRegIndex _result,
460                    IntRegIndex _dest, IntRegIndex _dest2,
461                    IntRegIndex _base, bool _add, int32_t _imm)
462        : Base(mnem, _machInst, __opClass, _result,
463                _dest, _dest2, _base, _add, _imm)
464    {}
465
466    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
467                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
468                    IntRegIndex _base, bool _add,
469                    int32_t _shiftAmt, ArmShiftType _shiftType,
470                    IntRegIndex _index)
471        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add,
472                _shiftAmt, _shiftType, _index)
473    {}
474
475    std::string
476    generateDisassembly(Addr pc, const SymbolTable *symtab) const
477    {
478        std::stringstream ss;
479        this->printInst(ss, Memory::AddrMd_PostIndex);
480        return ss.str();
481    }
482};
483}
484
485#endif //__ARCH_ARM_INSTS_MEM_HH__
486