arch: Add a virtual clone() method to PCState.

This will let callers create a separate copy of a PCState class
instance. This makes it more explicit when creating copies of a PCState
to make sure the programmer is more aware, and avoids having to know
what the actual type is to make a copy.

Change-Id: I728a278afdb55b800c753a5b7f65f62f4a80c043
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52035
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
diff --git a/src/arch/arm/pcstate.hh b/src/arch/arm/pcstate.hh
index b2a88c8..5bbad26 100644
--- a/src/arch/arm/pcstate.hh
+++ b/src/arch/arm/pcstate.hh
@@ -102,6 +102,8 @@
 
     PCState(Addr val) { set(val); }
 
+    PCStateBase *clone() const override { return new PCState(*this); }
+
     bool
     illegalExec() const
     {
diff --git a/src/arch/generic/pcstate.hh b/src/arch/generic/pcstate.hh
index c12b5cf..6d4e23e 100644
--- a/src/arch/generic/pcstate.hh
+++ b/src/arch/generic/pcstate.hh
@@ -68,6 +68,8 @@
     {
         return static_cast<const Target &>(*this);
     }
+
+    virtual PCStateBase *clone() const = 0;
 };
 
 namespace GenericISA
@@ -188,6 +190,12 @@
     SimplePCState() {}
     SimplePCState(Addr val) { set(val); }
 
+    PCStateBase *
+    clone() const override
+    {
+        return new SimplePCState<InstWidth>(*this);
+    }
+
     /**
      * Force this PC to reflect a particular value, resetting all its other
      * fields around it. This is useful for in place (re)initialization.
@@ -232,6 +240,11 @@
     typedef SimplePCState<InstWidth> Base;
 
   public:
+    PCStateBase *
+    clone() const override
+    {
+        return new UPCState<InstWidth>(*this);
+    }
 
     MicroPC upc() const { return this->_upc; }
     void upc(MicroPC val) { this->_upc = val; }
@@ -307,6 +320,11 @@
     Addr _nnpc;
 
   public:
+    PCStateBase *
+    clone() const override
+    {
+        return new DelaySlotPCState<InstWidth>(*this);
+    }
 
     Addr nnpc() const { return _nnpc; }
     void nnpc(Addr val) { _nnpc = val; }
@@ -387,6 +405,11 @@
     MicroPC _nupc;
 
   public:
+    PCStateBase *
+    clone() const override
+    {
+        return new DelaySlotUPCState<InstWidth>(*this);
+    }
 
     MicroPC upc() const { return _upc; }
     void upc(MicroPC val) { _upc = val; }
diff --git a/src/arch/power/pcstate.hh b/src/arch/power/pcstate.hh
index 7784005..c46b37e 100644
--- a/src/arch/power/pcstate.hh
+++ b/src/arch/power/pcstate.hh
@@ -47,6 +47,8 @@
   public:
     using GenericISA::SimplePCState<4>::SimplePCState;
 
+    PCStateBase *clone() const override { return new PCState(*this); }
+
     ByteOrder
     byteOrder() const
     {
diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh
index 0ab2b91..3187318 100644
--- a/src/arch/riscv/pcstate.hh
+++ b/src/arch/riscv/pcstate.hh
@@ -59,6 +59,8 @@
   public:
     using GenericISA::UPCState<4>::UPCState;
 
+    PCStateBase *clone() const override { return new PCState(*this); }
+
     void compressed(bool c) { _compressed = c; }
     bool compressed() const { return _compressed; }
 
diff --git a/src/arch/x86/pcstate.hh b/src/arch/x86/pcstate.hh
index 077ea15..28547f3 100644
--- a/src/arch/x86/pcstate.hh
+++ b/src/arch/x86/pcstate.hh
@@ -55,6 +55,8 @@
     uint8_t _size;
 
   public:
+    PCStateBase *clone() const override { return new PCState(*this); }
+
     void
     set(Addr val)
     {