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