types.hh revision 12104:edd63f9c6184
1/*
2 * Copyright (c) 2010 Gabe Black
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 */
30
31#ifndef __ARCH_GENERIC_TYPES_HH__
32#define __ARCH_GENERIC_TYPES_HH__
33
34#include <iostream>
35
36#include "base/trace.hh"
37#include "base/types.hh"
38#include "sim/serialize.hh"
39
40// Logical register index type.
41typedef uint16_t RegIndex;
42
43namespace GenericISA
44{
45
46// The guaranteed interface.
47class PCStateBase : public Serializable
48{
49  protected:
50    Addr _pc;
51    Addr _npc;
52
53    PCStateBase() : _pc(0), _npc(0) {}
54    PCStateBase(Addr val) : _pc(0), _npc(0) { set(val); }
55
56  public:
57    /**
58     * Returns the memory address the bytes of this instruction came from.
59     *
60     * @return Memory address of the current instruction's encoding.
61     */
62    Addr
63    instAddr() const
64    {
65        return _pc;
66    }
67
68    /**
69     * Returns the memory address the bytes of the next instruction came from.
70     *
71     * @return Memory address of the next instruction's encoding.
72     */
73    Addr
74    nextInstAddr() const
75    {
76        return _npc;
77    }
78
79    /**
80     * Returns the current micropc.
81     *
82     * @return The current micropc.
83     */
84    MicroPC
85    microPC() const
86    {
87        return 0;
88    }
89
90    /**
91     * Force this PC to reflect a particular value, resetting all its other
92     * fields around it. This is useful for in place (re)initialization.
93     *
94     * @param val The value to set the PC to.
95     */
96    void set(Addr val);
97
98    bool
99    operator == (const PCStateBase &opc) const
100    {
101        return _pc == opc._pc && _npc == opc._npc;
102    }
103
104    bool
105    operator != (const PCStateBase &opc) const
106    {
107        return !(*this == opc);
108    }
109
110    void
111    serialize(CheckpointOut &cp) const override
112    {
113        SERIALIZE_SCALAR(_pc);
114        SERIALIZE_SCALAR(_npc);
115    }
116
117    void
118    unserialize(CheckpointIn &cp) override
119    {
120        UNSERIALIZE_SCALAR(_pc);
121        UNSERIALIZE_SCALAR(_npc);
122    }
123};
124
125
126/*
127 * Different flavors of PC state. Only ISA specific code should rely on
128 * any particular type of PC state being available. All other code should
129 * use the interface above.
130 */
131
132// The most basic type of PC.
133template <class MachInst>
134class SimplePCState : public PCStateBase
135{
136  protected:
137    typedef PCStateBase Base;
138
139  public:
140
141    Addr pc() const { return _pc; }
142    void pc(Addr val) { _pc = val; }
143
144    Addr npc() const { return _npc; }
145    void npc(Addr val) { _npc = val; }
146
147    void
148    set(Addr val)
149    {
150        pc(val);
151        npc(val + sizeof(MachInst));
152    };
153
154    void
155    setNPC(Addr val)
156    {
157        npc(val);
158    }
159
160    SimplePCState() {}
161    SimplePCState(Addr val) { set(val); }
162
163    bool
164    branching() const
165    {
166        return this->npc() != this->pc() + sizeof(MachInst);
167    }
168
169    // Advance the PC.
170    void
171    advance()
172    {
173        _pc = _npc;
174        _npc += sizeof(MachInst);
175    }
176};
177
178template <class MachInst>
179std::ostream &
180operator<<(std::ostream & os, const SimplePCState<MachInst> &pc)
181{
182    ccprintf(os, "(%#x=>%#x)", pc.pc(), pc.npc());
183    return os;
184}
185
186// A PC and microcode PC.
187template <class MachInst>
188class UPCState : public SimplePCState<MachInst>
189{
190  protected:
191    typedef SimplePCState<MachInst> Base;
192
193    MicroPC _upc;
194    MicroPC _nupc;
195
196  public:
197
198    MicroPC upc() const { return _upc; }
199    void upc(MicroPC val) { _upc = val; }
200
201    MicroPC nupc() const { return _nupc; }
202    void nupc(MicroPC val) { _nupc = val; }
203
204    MicroPC
205    microPC() const
206    {
207        return _upc;
208    }
209
210    void
211    set(Addr val)
212    {
213        Base::set(val);
214        upc(0);
215        nupc(1);
216    }
217
218    UPCState() : _upc(0), _nupc(0) {}
219    UPCState(Addr val) : _upc(0), _nupc(0) { set(val); }
220
221    bool
222    branching() const
223    {
224        return this->npc() != this->pc() + sizeof(MachInst) ||
225               this->nupc() != this->upc() + 1;
226    }
227
228    // Advance the upc within the instruction.
229    void
230    uAdvance()
231    {
232        _upc = _nupc;
233        _nupc++;
234    }
235
236    // End the macroop by resetting the upc and advancing the regular pc.
237    void
238    uEnd()
239    {
240        this->advance();
241        _upc = 0;
242        _nupc = 1;
243    }
244
245    bool
246    operator == (const UPCState<MachInst> &opc) const
247    {
248        return Base::_pc == opc._pc &&
249               Base::_npc == opc._npc &&
250               _upc == opc._upc && _nupc == opc._nupc;
251    }
252
253    bool
254    operator != (const UPCState<MachInst> &opc) const
255    {
256        return !(*this == opc);
257    }
258
259    void
260    serialize(CheckpointOut &cp) const override
261    {
262        Base::serialize(cp);
263        SERIALIZE_SCALAR(_upc);
264        SERIALIZE_SCALAR(_nupc);
265    }
266
267    void
268    unserialize(CheckpointIn &cp) override
269    {
270        Base::unserialize(cp);
271        UNSERIALIZE_SCALAR(_upc);
272        UNSERIALIZE_SCALAR(_nupc);
273    }
274};
275
276template <class MachInst>
277std::ostream &
278operator<<(std::ostream & os, const UPCState<MachInst> &pc)
279{
280    ccprintf(os, "(%#x=>%#x).(%d=>%d)",
281            pc.pc(), pc.npc(), pc.upc(), pc.nupc());
282    return os;
283}
284
285// A PC with a delay slot.
286template <class MachInst>
287class DelaySlotPCState : public SimplePCState<MachInst>
288{
289  protected:
290    typedef SimplePCState<MachInst> Base;
291
292    Addr _nnpc;
293
294  public:
295
296    Addr nnpc() const { return _nnpc; }
297    void nnpc(Addr val) { _nnpc = val; }
298
299    void
300    set(Addr val)
301    {
302        Base::set(val);
303        nnpc(val + 2 * sizeof(MachInst));
304    }
305
306    DelaySlotPCState() {}
307    DelaySlotPCState(Addr val) { set(val); }
308
309    bool
310    branching() const
311    {
312        return !(this->nnpc() == this->npc() + sizeof(MachInst) &&
313                 (this->npc() == this->pc() + sizeof(MachInst) ||
314                  this->npc() == this->pc() + 2 * sizeof(MachInst)));
315    }
316
317    // Advance the PC.
318    void
319    advance()
320    {
321        Base::_pc = Base::_npc;
322        Base::_npc = _nnpc;
323        _nnpc += sizeof(MachInst);
324    }
325
326    bool
327    operator == (const DelaySlotPCState<MachInst> &opc) const
328    {
329        return Base::_pc == opc._pc &&
330               Base::_npc == opc._npc &&
331               _nnpc == opc._nnpc;
332    }
333
334    bool
335    operator != (const DelaySlotPCState<MachInst> &opc) const
336    {
337        return !(*this == opc);
338    }
339
340    void
341    serialize(CheckpointOut &cp) const override
342    {
343        Base::serialize(cp);
344        SERIALIZE_SCALAR(_nnpc);
345    }
346
347    void
348    unserialize(CheckpointIn &cp) override
349    {
350        Base::unserialize(cp);
351        UNSERIALIZE_SCALAR(_nnpc);
352    }
353};
354
355template <class MachInst>
356std::ostream &
357operator<<(std::ostream & os, const DelaySlotPCState<MachInst> &pc)
358{
359    ccprintf(os, "(%#x=>%#x=>%#x)",
360            pc.pc(), pc.npc(), pc.nnpc());
361    return os;
362}
363
364// A PC with a delay slot and a microcode PC.
365template <class MachInst>
366class DelaySlotUPCState : public DelaySlotPCState<MachInst>
367{
368  protected:
369    typedef DelaySlotPCState<MachInst> Base;
370
371    MicroPC _upc;
372    MicroPC _nupc;
373
374  public:
375
376    MicroPC upc() const { return _upc; }
377    void upc(MicroPC val) { _upc = val; }
378
379    MicroPC nupc() const { return _nupc; }
380    void nupc(MicroPC val) { _nupc = val; }
381
382    MicroPC
383    microPC() const
384    {
385        return _upc;
386    }
387
388    void
389    set(Addr val)
390    {
391        Base::set(val);
392        upc(0);
393        nupc(1);
394    }
395
396    DelaySlotUPCState() {}
397    DelaySlotUPCState(Addr val) { set(val); }
398
399    bool
400    branching() const
401    {
402        return Base::branching() || this->nupc() != this->upc() + 1;
403    }
404
405    // Advance the upc within the instruction.
406    void
407    uAdvance()
408    {
409        _upc = _nupc;
410        _nupc++;
411    }
412
413    // End the macroop by resetting the upc and advancing the regular pc.
414    void
415    uEnd()
416    {
417        this->advance();
418        _upc = 0;
419        _nupc = 1;
420    }
421
422    bool
423    operator == (const DelaySlotUPCState<MachInst> &opc) const
424    {
425        return Base::_pc == opc._pc &&
426               Base::_npc == opc._npc &&
427               Base::_nnpc == opc._nnpc &&
428               _upc == opc._upc && _nupc == opc._nupc;
429    }
430
431    bool
432    operator != (const DelaySlotUPCState<MachInst> &opc) const
433    {
434        return !(*this == opc);
435    }
436
437    void
438    serialize(CheckpointOut &cp) const override
439    {
440        Base::serialize(cp);
441        SERIALIZE_SCALAR(_upc);
442        SERIALIZE_SCALAR(_nupc);
443    }
444
445    void
446    unserialize(CheckpointIn &cp) override
447    {
448        Base::unserialize(cp);
449        UNSERIALIZE_SCALAR(_upc);
450        UNSERIALIZE_SCALAR(_nupc);
451    }
452};
453
454template <class MachInst>
455std::ostream &
456operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc)
457{
458    ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)",
459            pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc());
460    return os;
461}
462
463}
464
465#endif
466