arch,cpu: Convert ExecContext::pcState to use PCStateBase.

Some places need persistent temporaries for the return values of
ThreadContext::pcState(), which is currently by value.

Change-Id: Icd4924f1d16ebe1c99c54ed47616733422340cfe
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52057
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/arm/insts/pseudo.cc b/src/arch/arm/insts/pseudo.cc
index 7d61b7e..ca5e594 100644
--- a/src/arch/arm/insts/pseudo.cc
+++ b/src/arch/arm/insts/pseudo.cc
@@ -60,8 +60,7 @@
 Fault
 DecoderFaultInst::execute(ExecContext *xc, Trace::InstRecord *traceData) const
 {
-    const PCState pc_state(xc->pcState());
-    const Addr pc(pc_state.instAddr());
+    const Addr pc = xc->pcState().instAddr();
 
     switch (faultId) {
       case DecoderFault::UNALIGNED:
@@ -203,7 +202,7 @@
 Fault
 DebugStep::execute(ExecContext *xc, Trace::InstRecord *traceData) const
 {
-    PCState pc_state(xc->pcState());
+    PCState pc_state = xc->pcState().as<PCState>();
     pc_state.debugStep(false);
     xc->pcState(pc_state);
 
@@ -213,7 +212,6 @@
 
     return std::make_shared<SoftwareStepFault>(machInst, ldx,
                                                pc_state.stepped());
-
 }
 
 } // namespace gem5
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh
index 07181c2..e0b2ab5 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -325,13 +325,13 @@
     static inline Addr
     readPC(ExecContext *xc)
     {
-        return xc->pcState().instPC();
+        return xc->pcState().as<PCState>().instPC();
     }
 
     static inline void
     setNextPC(ExecContext *xc, Addr val)
     {
-        PCState pc = xc->pcState();
+        PCState pc = xc->pcState().as<PCState>();
         pc.instNPC(val);
         xc->pcState(pc);
     }
@@ -374,7 +374,7 @@
     static inline void
     setIWNextPC(ExecContext *xc, Addr val)
     {
-        PCState pc = xc->pcState();
+        PCState pc = xc->pcState().as<PCState>();
         pc.instIWNPC(val);
         xc->pcState(pc);
     }
@@ -384,7 +384,7 @@
     static inline void
     setAIWNextPC(ExecContext *xc, Addr val)
     {
-        PCState pc = xc->pcState();
+        PCState pc = xc->pcState().as<PCState>();
         pc.instAIWNPC(val);
         xc->pcState(pc);
     }
diff --git a/src/arch/isa_parser/isa_parser.py b/src/arch/isa_parser/isa_parser.py
index 6e0373a..901662f 100755
--- a/src/arch/isa_parser/isa_parser.py
+++ b/src/arch/isa_parser/isa_parser.py
@@ -152,7 +152,8 @@
 
             myDict['op_rd'] = operands.concatAttrStrings('op_rd')
             if operands.readPC:
-                myDict['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \
+                myDict['op_rd'] = \
+                        'set(__parserAutoPCState, xc->pcState());\n' + \
                                   myDict['op_rd']
 
             # Compose the op_wb string. If we're going to write back the
diff --git a/src/arch/isa_parser/operand_types.py b/src/arch/isa_parser/operand_types.py
index 8b493da..a029795 100755
--- a/src/arch/isa_parser/operand_types.py
+++ b/src/arch/isa_parser/operand_types.py
@@ -751,7 +751,8 @@
                 (self.base_name, self.reg_spec)
         else:
             # The whole PC state itself.
-            return '%s = xc->pcState();\n' % self.base_name
+            return f'{self.base_name} = ' \
+                    f'xc->pcState().as<{self.parser.namespace}::PCState>();\n'
 
     def makeWrite(self, predWrite):
         if self.reg_spec:
@@ -760,7 +761,7 @@
                 (self.reg_spec, self.base_name)
         else:
             # The whole PC state itself.
-            return 'xc->pcState(%s);\n' % self.base_name
+            return f'xc->pcState({self.base_name});\n'
 
     def makeDecl(self):
         ctype = f'{self.parser.namespace}::PCState'
diff --git a/src/arch/power/isa/formats/unknown.isa b/src/arch/power/isa/formats/unknown.isa
index a627f88..f68aff8 100644
--- a/src/arch/power/isa/formats/unknown.isa
+++ b/src/arch/power/isa/formats/unknown.isa
@@ -72,9 +72,9 @@
     Fault
     Unknown::execute(ExecContext *xc, Trace::InstRecord *traceData) const
     {
-        inform("attempt to execute unknown instruction at %#x"
+        inform("attempt to execute unknown instruction at %s"
                "(inst 0x%08x, opcode 0x%x, binary: %s)",
-               xc->pcState().pc(), machInst, PO, inst2string(machInst));
+               xc->pcState(), machInst, PO, inst2string(machInst));
         return std::make_shared<UnimplementedOpcodeFault>();
     }
 }};
diff --git a/src/arch/riscv/faults.hh b/src/arch/riscv/faults.hh
index 1ea8f70..1bc671e 100644
--- a/src/arch/riscv/faults.hh
+++ b/src/arch/riscv/faults.hh
@@ -243,8 +243,9 @@
     const PCState pcState;
 
   public:
-    BreakpointFault(const PCState &pc)
-        : RiscvFault("Breakpoint", FaultType::OTHERS, BREAKPOINT), pcState(pc)
+    BreakpointFault(const PCStateBase &pc)
+        : RiscvFault("Breakpoint", FaultType::OTHERS, BREAKPOINT),
+        pcState(pc.as<PCState>())
     {}
 
     RegVal trap_value() const override { return pcState.pc(); }
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index 1ed7e0d..2471bae 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -354,13 +354,19 @@
         return (thread->htmTransactionStarts - thread->htmTransactionStops);
     }
 
-    TheISA::PCState pcState() const override { return thread->pcState(); }
+    mutable TheISA::PCState tempPCState;
+    const PCStateBase &
+    pcState() const override
+    {
+        set(tempPCState, thread->pcState());
+        return tempPCState;
+    }
     void
-    pcState(const TheISA::PCState &val) override
+    pcState(const PCStateBase &val) override
     {
         DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
                          val, thread->pcState());
-        thread->pcState(val);
+        thread->pcState(val.as<TheISA::PCState>());
     }
     Addr instAddr() { return thread->instAddr(); }
     MicroPC microPC() { return thread->microPC(); }
diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh
index 8550815..b88c895 100644
--- a/src/cpu/exec_context.hh
+++ b/src/cpu/exec_context.hh
@@ -181,8 +181,8 @@
      * @{
      * @name PC Control
      */
-    virtual TheISA::PCState pcState() const = 0;
-    virtual void pcState(const TheISA::PCState &val) = 0;
+    virtual const PCStateBase &pcState() const = 0;
+    virtual void pcState(const PCStateBase &val) = 0;
     /** @} */
 
     /**
diff --git a/src/cpu/minor/exec_context.hh b/src/cpu/minor/exec_context.hh
index ba0be03..2c5a4b2 100644
--- a/src/cpu/minor/exec_context.hh
+++ b/src/cpu/minor/exec_context.hh
@@ -94,7 +94,7 @@
         inst(inst_)
     {
         DPRINTF(MinorExecute, "ExecContext setting PC: %s\n", *inst->pc);
-        pcState(inst->pc->as<TheISA::PCState>());
+        pcState(*inst->pc);
         setPredicate(inst->readPredicate());
         setMemAccPredicate(inst->readMemAccPredicate());
         thread.setIntReg(zeroReg, 0);
@@ -299,16 +299,18 @@
         return 0;
     }
 
-    TheISA::PCState
+    mutable TheISA::PCState tempPCState;
+    const PCStateBase &
     pcState() const override
     {
-        return thread.pcState();
+        set(tempPCState, thread.pcState());
+        return tempPCState;
     }
 
     void
-    pcState(const TheISA::PCState &val) override
+    pcState(const PCStateBase &val) override
     {
-        thread.pcState(val);
+        thread.pcState(val.as<TheISA::PCState>());
     }
 
     RegVal
diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh
index 8c8a99a..832d5e8 100644
--- a/src/cpu/o3/dyn_inst.hh
+++ b/src/cpu/o3/dyn_inst.hh
@@ -898,14 +898,14 @@
     }
 
     /** Read the PC state of this instruction. */
-    TheISA::PCState
+    const PCStateBase &
     pcState() const override
     {
-        return pc->as<TheISA::PCState>();
+        return *pc;
     }
 
     /** Set the PC state of this instruction. */
-    void pcState(const TheISA::PCState &val) override { set(pc, val); }
+    void pcState(const PCStateBase &val) override { set(pc, val); }
 
     /** Read the PC of this instruction. */
     Addr instAddr() const { return pc->instAddr(); }
diff --git a/src/cpu/o3/iew.cc b/src/cpu/o3/iew.cc
index 8dbd5b3..062a566 100644
--- a/src/cpu/o3/iew.cc
+++ b/src/cpu/o3/iew.cc
@@ -461,7 +461,8 @@
             inst->seqNum < toCommit->squashedSeqNum[tid]) {
         toCommit->squash[tid] = true;
         toCommit->squashedSeqNum[tid] = inst->seqNum;
-        toCommit->branchTaken[tid] = inst->pcState().branching();
+        toCommit->branchTaken[tid] =
+            inst->pcState().as<TheISA::PCState>().branching();
 
         set(toCommit->pc[tid], inst->pcState());
         inst->staticInst->advancePC(*toCommit->pc[tid]);
diff --git a/src/cpu/simple/exec_context.hh b/src/cpu/simple/exec_context.hh
index d652873..305f110 100644
--- a/src/cpu/simple/exec_context.hh
+++ b/src/cpu/simple/exec_context.hh
@@ -467,16 +467,18 @@
         thread->setMiscReg(misc_reg, val);
     }
 
-    TheISA::PCState
+    mutable TheISA::PCState tempPCState;
+    const PCStateBase &
     pcState() const override
     {
-        return thread->pcState();
+        set(tempPCState, thread->pcState());
+        return tempPCState;
     }
 
     void
-    pcState(const TheISA::PCState &val) override
+    pcState(const PCStateBase &val) override
     {
-        thread->pcState(val);
+        thread->pcState(val.as<TheISA::PCState>());
     }
 
     Fault