types.hh revision 12109:f29e9c5418aa
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
43/** Logical vector register elem index type. */
44using ElemIndex = uint16_t;
45
46namespace GenericISA
47{
48
49// The guaranteed interface.
50class PCStateBase : public Serializable
51{
52  protected:
53    Addr _pc;
54    Addr _npc;
55
56    PCStateBase() : _pc(0), _npc(0) {}
57    PCStateBase(Addr val) : _pc(0), _npc(0) { set(val); }
58
59  public:
60    /**
61     * Returns the memory address the bytes of this instruction came from.
62     *
63     * @return Memory address of the current instruction's encoding.
64     */
65    Addr
66    instAddr() const
67    {
68        return _pc;
69    }
70
71    /**
72     * Returns the memory address the bytes of the next instruction came from.
73     *
74     * @return Memory address of the next instruction's encoding.
75     */
76    Addr
77    nextInstAddr() const
78    {
79        return _npc;
80    }
81
82    /**
83     * Returns the current micropc.
84     *
85     * @return The current micropc.
86     */
87    MicroPC
88    microPC() const
89    {
90        return 0;
91    }
92
93    /**
94     * Force this PC to reflect a particular value, resetting all its other
95     * fields around it. This is useful for in place (re)initialization.
96     *
97     * @param val The value to set the PC to.
98     */
99    void set(Addr val);
100
101    bool
102    operator == (const PCStateBase &opc) const
103    {
104        return _pc == opc._pc && _npc == opc._npc;
105    }
106
107    bool
108    operator != (const PCStateBase &opc) const
109    {
110        return !(*this == opc);
111    }
112
113    void
114    serialize(CheckpointOut &cp) const override
115    {
116        SERIALIZE_SCALAR(_pc);
117        SERIALIZE_SCALAR(_npc);
118    }
119
120    void
121    unserialize(CheckpointIn &cp) override
122    {
123        UNSERIALIZE_SCALAR(_pc);
124        UNSERIALIZE_SCALAR(_npc);
125    }
126};
127
128
129/*
130 * Different flavors of PC state. Only ISA specific code should rely on
131 * any particular type of PC state being available. All other code should
132 * use the interface above.
133 */
134
135// The most basic type of PC.
136template <class MachInst>
137class SimplePCState : public PCStateBase
138{
139  protected:
140    typedef PCStateBase Base;
141
142  public:
143
144    Addr pc() const { return _pc; }
145    void pc(Addr val) { _pc = val; }
146
147    Addr npc() const { return _npc; }
148    void npc(Addr val) { _npc = val; }
149
150    void
151    set(Addr val)
152    {
153        pc(val);
154        npc(val + sizeof(MachInst));
155    };
156
157    void
158    setNPC(Addr val)
159    {
160        npc(val);
161    }
162
163    SimplePCState() {}
164    SimplePCState(Addr val) { set(val); }
165
166    bool
167    branching() const
168    {
169        return this->npc() != this->pc() + sizeof(MachInst);
170    }
171
172    // Advance the PC.
173    void
174    advance()
175    {
176        _pc = _npc;
177        _npc += sizeof(MachInst);
178    }
179};
180
181template <class MachInst>
182std::ostream &
183operator<<(std::ostream & os, const SimplePCState<MachInst> &pc)
184{
185    ccprintf(os, "(%#x=>%#x)", pc.pc(), pc.npc());
186    return os;
187}
188
189// A PC and microcode PC.
190template <class MachInst>
191class UPCState : public SimplePCState<MachInst>
192{
193  protected:
194    typedef SimplePCState<MachInst> Base;
195
196    MicroPC _upc;
197    MicroPC _nupc;
198
199  public:
200
201    MicroPC upc() const { return _upc; }
202    void upc(MicroPC val) { _upc = val; }
203
204    MicroPC nupc() const { return _nupc; }
205    void nupc(MicroPC val) { _nupc = val; }
206
207    MicroPC
208    microPC() const
209    {
210        return _upc;
211    }
212
213    void
214    set(Addr val)
215    {
216        Base::set(val);
217        upc(0);
218        nupc(1);
219    }
220
221    UPCState() : _upc(0), _nupc(0) {}
222    UPCState(Addr val) : _upc(0), _nupc(0) { set(val); }
223
224    bool
225    branching() const
226    {
227        return this->npc() != this->pc() + sizeof(MachInst) ||
228               this->nupc() != this->upc() + 1;
229    }
230
231    // Advance the upc within the instruction.
232    void
233    uAdvance()
234    {
235        _upc = _nupc;
236        _nupc++;
237    }
238
239    // End the macroop by resetting the upc and advancing the regular pc.
240    void
241    uEnd()
242    {
243        this->advance();
244        _upc = 0;
245        _nupc = 1;
246    }
247
248    bool
249    operator == (const UPCState<MachInst> &opc) const
250    {
251        return Base::_pc == opc._pc &&
252               Base::_npc == opc._npc &&
253               _upc == opc._upc && _nupc == opc._nupc;
254    }
255
256    bool
257    operator != (const UPCState<MachInst> &opc) const
258    {
259        return !(*this == opc);
260    }
261
262    void
263    serialize(CheckpointOut &cp) const override
264    {
265        Base::serialize(cp);
266        SERIALIZE_SCALAR(_upc);
267        SERIALIZE_SCALAR(_nupc);
268    }
269
270    void
271    unserialize(CheckpointIn &cp) override
272    {
273        Base::unserialize(cp);
274        UNSERIALIZE_SCALAR(_upc);
275        UNSERIALIZE_SCALAR(_nupc);
276    }
277};
278
279template <class MachInst>
280std::ostream &
281operator<<(std::ostream & os, const UPCState<MachInst> &pc)
282{
283    ccprintf(os, "(%#x=>%#x).(%d=>%d)",
284            pc.pc(), pc.npc(), pc.upc(), pc.nupc());
285    return os;
286}
287
288// A PC with a delay slot.
289template <class MachInst>
290class DelaySlotPCState : public SimplePCState<MachInst>
291{
292  protected:
293    typedef SimplePCState<MachInst> Base;
294
295    Addr _nnpc;
296
297  public:
298
299    Addr nnpc() const { return _nnpc; }
300    void nnpc(Addr val) { _nnpc = val; }
301
302    void
303    set(Addr val)
304    {
305        Base::set(val);
306        nnpc(val + 2 * sizeof(MachInst));
307    }
308
309    DelaySlotPCState() {}
310    DelaySlotPCState(Addr val) { set(val); }
311
312    bool
313    branching() const
314    {
315        return !(this->nnpc() == this->npc() + sizeof(MachInst) &&
316                 (this->npc() == this->pc() + sizeof(MachInst) ||
317                  this->npc() == this->pc() + 2 * sizeof(MachInst)));
318    }
319
320    // Advance the PC.
321    void
322    advance()
323    {
324        Base::_pc = Base::_npc;
325        Base::_npc = _nnpc;
326        _nnpc += sizeof(MachInst);
327    }
328
329    bool
330    operator == (const DelaySlotPCState<MachInst> &opc) const
331    {
332        return Base::_pc == opc._pc &&
333               Base::_npc == opc._npc &&
334               _nnpc == opc._nnpc;
335    }
336
337    bool
338    operator != (const DelaySlotPCState<MachInst> &opc) const
339    {
340        return !(*this == opc);
341    }
342
343    void
344    serialize(CheckpointOut &cp) const override
345    {
346        Base::serialize(cp);
347        SERIALIZE_SCALAR(_nnpc);
348    }
349
350    void
351    unserialize(CheckpointIn &cp) override
352    {
353        Base::unserialize(cp);
354        UNSERIALIZE_SCALAR(_nnpc);
355    }
356};
357
358template <class MachInst>
359std::ostream &
360operator<<(std::ostream & os, const DelaySlotPCState<MachInst> &pc)
361{
362    ccprintf(os, "(%#x=>%#x=>%#x)",
363            pc.pc(), pc.npc(), pc.nnpc());
364    return os;
365}
366
367// A PC with a delay slot and a microcode PC.
368template <class MachInst>
369class DelaySlotUPCState : public DelaySlotPCState<MachInst>
370{
371  protected:
372    typedef DelaySlotPCState<MachInst> Base;
373
374    MicroPC _upc;
375    MicroPC _nupc;
376
377  public:
378
379    MicroPC upc() const { return _upc; }
380    void upc(MicroPC val) { _upc = val; }
381
382    MicroPC nupc() const { return _nupc; }
383    void nupc(MicroPC val) { _nupc = val; }
384
385    MicroPC
386    microPC() const
387    {
388        return _upc;
389    }
390
391    void
392    set(Addr val)
393    {
394        Base::set(val);
395        upc(0);
396        nupc(1);
397    }
398
399    DelaySlotUPCState() {}
400    DelaySlotUPCState(Addr val) { set(val); }
401
402    bool
403    branching() const
404    {
405        return Base::branching() || this->nupc() != this->upc() + 1;
406    }
407
408    // Advance the upc within the instruction.
409    void
410    uAdvance()
411    {
412        _upc = _nupc;
413        _nupc++;
414    }
415
416    // End the macroop by resetting the upc and advancing the regular pc.
417    void
418    uEnd()
419    {
420        this->advance();
421        _upc = 0;
422        _nupc = 1;
423    }
424
425    bool
426    operator == (const DelaySlotUPCState<MachInst> &opc) const
427    {
428        return Base::_pc == opc._pc &&
429               Base::_npc == opc._npc &&
430               Base::_nnpc == opc._nnpc &&
431               _upc == opc._upc && _nupc == opc._nupc;
432    }
433
434    bool
435    operator != (const DelaySlotUPCState<MachInst> &opc) const
436    {
437        return !(*this == opc);
438    }
439
440    void
441    serialize(CheckpointOut &cp) const override
442    {
443        Base::serialize(cp);
444        SERIALIZE_SCALAR(_upc);
445        SERIALIZE_SCALAR(_nupc);
446    }
447
448    void
449    unserialize(CheckpointIn &cp) override
450    {
451        Base::unserialize(cp);
452        UNSERIALIZE_SCALAR(_upc);
453        UNSERIALIZE_SCALAR(_nupc);
454    }
455};
456
457template <class MachInst>
458std::ostream &
459operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc)
460{
461    ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)",
462            pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc());
463    return os;
464}
465
466}
467
468#endif
469