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