mem.hh revision 7303
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 Swap : public PredOp
51{
52  protected:
53    IntRegIndex dest;
54    IntRegIndex op1;
55    IntRegIndex base;
56
57    Swap(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
58         IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _base)
59        : PredOp(mnem, _machInst, __opClass),
60          dest(_dest), op1(_op1), base(_base)
61    {}
62
63    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
64};
65
66// The address is a base register plus an immediate.
67class RfeOp : public PredOp
68{
69  public:
70    enum AddrMode {
71        DecrementAfter,
72        DecrementBefore,
73        IncrementAfter,
74        IncrementBefore
75    };
76  protected:
77    IntRegIndex base;
78    AddrMode mode;
79    bool wb;
80
81    RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
82          IntRegIndex _base, AddrMode _mode, bool _wb)
83        : PredOp(mnem, _machInst, __opClass),
84          base(_base), mode(_mode), wb(_wb)
85    {}
86
87    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
88};
89
90class Memory : public PredOp
91{
92  public:
93    enum AddrMode {
94        AddrMd_Offset,
95        AddrMd_PreIndex,
96        AddrMd_PostIndex
97    };
98
99  protected:
100
101    IntRegIndex dest;
102    IntRegIndex base;
103    bool add;
104
105    Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
106           IntRegIndex _dest, IntRegIndex _base, bool _add)
107        : PredOp(mnem, _machInst, __opClass),
108          dest(_dest), base(_base), add(_add)
109    {}
110
111    virtual void
112    printOffset(std::ostream &os) const
113    {}
114
115    virtual void
116    printDest(std::ostream &os) const
117    {
118        printReg(os, dest);
119    }
120
121    void printInst(std::ostream &os, AddrMode addrMode) const;
122};
123
124// The address is a base register plus an immediate.
125class MemoryImm : public Memory
126{
127  protected:
128    int32_t imm;
129
130    MemoryImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
131              IntRegIndex _dest, IntRegIndex _base, bool _add, int32_t _imm)
132        : Memory(mnem, _machInst, __opClass, _dest, _base, _add), imm(_imm)
133    {}
134
135    void
136    printOffset(std::ostream &os) const
137    {
138        int32_t pImm = imm;
139        if (!add)
140            pImm = -pImm;
141        ccprintf(os, "#%d", pImm);
142    }
143};
144
145class MemoryExImm : public MemoryImm
146{
147  protected:
148    IntRegIndex result;
149
150    MemoryExImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
151                IntRegIndex _result, IntRegIndex _dest, IntRegIndex _base,
152                bool _add, int32_t _imm)
153        : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm),
154                    result(_result)
155    {}
156
157    void
158    printDest(std::ostream &os) const
159    {
160        printReg(os, result);
161        os << ", ";
162        MemoryImm::printDest(os);
163    }
164};
165
166// The address is a base register plus an immediate.
167class MemoryDImm : public MemoryImm
168{
169  protected:
170    IntRegIndex dest2;
171
172    MemoryDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
173              IntRegIndex _dest, IntRegIndex _dest2,
174              IntRegIndex _base, bool _add, int32_t _imm)
175        : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm),
176          dest2(_dest2)
177    {}
178
179    void
180    printDest(std::ostream &os) const
181    {
182        MemoryImm::printDest(os);
183        os << ", ";
184        printReg(os, dest2);
185    }
186};
187
188class MemoryExDImm : public MemoryDImm
189{
190  protected:
191    IntRegIndex result;
192
193    MemoryExDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
194                 IntRegIndex _result, IntRegIndex _dest, IntRegIndex _dest2,
195                 IntRegIndex _base, bool _add, int32_t _imm)
196        : MemoryDImm(mnem, _machInst, __opClass, _dest, _dest2,
197                     _base, _add, _imm), result(_result)
198    {}
199
200    void
201    printDest(std::ostream &os) const
202    {
203        printReg(os, result);
204        os << ", ";
205        MemoryDImm::printDest(os);
206    }
207};
208
209// The address is a shifted register plus an immediate
210class MemoryReg : public Memory
211{
212  protected:
213    int32_t shiftAmt;
214    ArmShiftType shiftType;
215    IntRegIndex index;
216
217    MemoryReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
218              IntRegIndex _dest, IntRegIndex _base, bool _add,
219              int32_t _shiftAmt, ArmShiftType _shiftType,
220              IntRegIndex _index)
221        : Memory(mnem, _machInst, __opClass, _dest, _base, _add),
222          shiftAmt(_shiftAmt), shiftType(_shiftType), index(_index)
223    {}
224
225    void
226    printOffset(std::ostream &os) const
227    {
228        if (!add)
229            os << "-";
230        printReg(os, index);
231        if (shiftType != LSL || shiftAmt != 0) {
232            switch (shiftType) {
233              case LSL:
234                ccprintf(os, " LSL #%d", shiftAmt);
235                break;
236              case LSR:
237                if (shiftAmt == 0) {
238                    ccprintf(os, " LSR #%d", 32);
239                } else {
240                    ccprintf(os, " LSR #%d", shiftAmt);
241                }
242                break;
243              case ASR:
244                if (shiftAmt == 0) {
245                    ccprintf(os, " ASR #%d", 32);
246                } else {
247                    ccprintf(os, " ASR #%d", shiftAmt);
248                }
249                break;
250              case ROR:
251                if (shiftAmt == 0) {
252                    ccprintf(os, " RRX");
253                } else {
254                    ccprintf(os, " ROR #%d", shiftAmt);
255                }
256                break;
257            }
258        }
259    }
260};
261
262class MemoryDReg : public MemoryReg
263{
264  protected:
265    IntRegIndex dest2;
266
267    MemoryDReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
268               IntRegIndex _dest, IntRegIndex _dest2,
269               IntRegIndex _base, bool _add,
270               int32_t _shiftAmt, ArmShiftType _shiftType,
271               IntRegIndex _index)
272        : MemoryReg(mnem, _machInst, __opClass, _dest, _base, _add,
273                    _shiftAmt, _shiftType, _index),
274          dest2(_dest2)
275    {}
276
277    void
278    printDest(std::ostream &os) const
279    {
280        MemoryReg::printDest(os);
281        os << ", ";
282        printReg(os, dest2);
283    }
284};
285
286template<class Base>
287class MemoryOffset : public Base
288{
289  protected:
290    MemoryOffset(const char *mnem, ExtMachInst _machInst,
291                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
292                 bool _add, int32_t _imm)
293        : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm)
294    {}
295
296    MemoryOffset(const char *mnem, ExtMachInst _machInst,
297                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
298                 bool _add, int32_t _shiftAmt, ArmShiftType _shiftType,
299                 IntRegIndex _index)
300        : Base(mnem, _machInst, __opClass, _dest, _base, _add,
301                _shiftAmt, _shiftType, _index)
302    {}
303
304    MemoryOffset(const char *mnem, ExtMachInst _machInst,
305                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
306                 IntRegIndex _base, bool _add, int32_t _imm)
307        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
308    {}
309
310    MemoryOffset(const char *mnem, ExtMachInst _machInst,
311                 OpClass __opClass, IntRegIndex _result,
312                 IntRegIndex _dest, IntRegIndex _dest2,
313                 IntRegIndex _base, bool _add, int32_t _imm)
314        : Base(mnem, _machInst, __opClass, _result,
315                _dest, _dest2, _base, _add, _imm)
316    {}
317
318    MemoryOffset(const char *mnem, ExtMachInst _machInst,
319                 OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
320                 IntRegIndex _base, bool _add,
321                 int32_t _shiftAmt, ArmShiftType _shiftType,
322                 IntRegIndex _index)
323        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add,
324                _shiftAmt, _shiftType, _index)
325    {}
326
327    std::string
328    generateDisassembly(Addr pc, const SymbolTable *symtab) const
329    {
330        std::stringstream ss;
331        this->printInst(ss, Memory::AddrMd_Offset);
332        return ss.str();
333    }
334};
335
336template<class Base>
337class MemoryPreIndex : public Base
338{
339  protected:
340    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
341                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
342                   bool _add, int32_t _imm)
343        : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm)
344    {}
345
346    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
347                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
348                   bool _add, int32_t _shiftAmt, ArmShiftType _shiftType,
349                   IntRegIndex _index)
350        : Base(mnem, _machInst, __opClass, _dest, _base, _add,
351                _shiftAmt, _shiftType, _index)
352    {}
353
354    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
355                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
356                   IntRegIndex _base, bool _add, int32_t _imm)
357        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
358    {}
359
360    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
361                   OpClass __opClass, IntRegIndex _result,
362                   IntRegIndex _dest, IntRegIndex _dest2,
363                   IntRegIndex _base, bool _add, int32_t _imm)
364        : Base(mnem, _machInst, __opClass, _result,
365                _dest, _dest2, _base, _add, _imm)
366    {}
367
368    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
369                   OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
370                   IntRegIndex _base, bool _add,
371                   int32_t _shiftAmt, ArmShiftType _shiftType,
372                   IntRegIndex _index)
373        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add,
374                _shiftAmt, _shiftType, _index)
375    {}
376
377    std::string
378    generateDisassembly(Addr pc, const SymbolTable *symtab) const
379    {
380        std::stringstream ss;
381        this->printInst(ss, Memory::AddrMd_PreIndex);
382        return ss.str();
383    }
384};
385
386template<class Base>
387class MemoryPostIndex : public Base
388{
389  protected:
390    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
391                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
392                    bool _add, int32_t _imm)
393        : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm)
394    {}
395
396    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
397                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _base,
398                    bool _add, int32_t _shiftAmt, ArmShiftType _shiftType,
399                    IntRegIndex _index)
400        : Base(mnem, _machInst, __opClass, _dest, _base, _add,
401                _shiftAmt, _shiftType, _index)
402    {}
403
404    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
405                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
406                    IntRegIndex _base, bool _add, int32_t _imm)
407        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
408    {}
409
410    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
411                    OpClass __opClass, IntRegIndex _result,
412                    IntRegIndex _dest, IntRegIndex _dest2,
413                    IntRegIndex _base, bool _add, int32_t _imm)
414        : Base(mnem, _machInst, __opClass, _result,
415                _dest, _dest2, _base, _add, _imm)
416    {}
417
418    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
419                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
420                    IntRegIndex _base, bool _add,
421                    int32_t _shiftAmt, ArmShiftType _shiftType,
422                    IntRegIndex _index)
423        : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add,
424                _shiftAmt, _shiftType, _index)
425    {}
426
427    std::string
428    generateDisassembly(Addr pc, const SymbolTable *symtab) const
429    {
430        std::stringstream ss;
431        this->printInst(ss, Memory::AddrMd_PostIndex);
432        return ss.str();
433    }
434};
435}
436
437#endif //__ARCH_ARM_INSTS_MEM_HH__
438