arch-power: Add MSR and associated dependencies
authorSandipan Das <sandipan@linux.ibm.com>
Sat, 6 Feb 2021 11:57:58 +0000 (17:27 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Mon, 15 Feb 2021 08:32:38 +0000 (14:02 +0530)
This adds the definition of the Machine State Register
(MSR) in preparation for multi-mode support. The MSR
has bits that define the state of the processor. This
defines all the bitfields and sets the ones that are
typically used for userspace environments.

In preparation for multi-mode support, the SF and LE
bits are used by instructions to check if the simulation
is running in 64-bit mode and if memory accesses are to
be performed in little endian byte order respectively.
This introduces changes in areas such as target address
computation for branch instructions, carry and overflow
computation for arithmetic instructions, etc.

Change-Id: If9ac69415ca85b0c873bd8579e7d1bd2219eac62
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
src/arch/power/insts/branch.cc
src/arch/power/insts/branch.hh
src/arch/power/isa/formats/branch.isa
src/arch/power/isa/formats/integer.isa
src/arch/power/isa/formats/mem.isa
src/arch/power/isa/operands.isa
src/arch/power/miscregs.hh
src/arch/power/process.cc

index 3747bf1b73c1dbc6f5b556755eb7e2391e3d5a29..f54185aef0b516614bc3a1116154dcd450f49508 100644 (file)
@@ -54,13 +54,18 @@ PCDependentDisassembly::disassemble(
 
 
 PowerISA::PCState
-BranchOp::branchTarget(const PowerISA::PCState &pc) const
+BranchOp::branchTarget(ThreadContext *tc) const
 {
+    Msr msr = tc->readMiscReg(MISCREG_MSR);
+    Addr addr;
+
     if (aaSet) {
-        return disp;
+        addr = disp;
     } else {
-        return pc.pc() + disp;
+        addr = tc->pcState().pc() + disp;
     }
+
+    return msr.sf ? addr : addr & UINT32_MAX;
 }
 
 
@@ -96,13 +101,18 @@ BranchOp::generateDisassembly(
 
 
 PowerISA::PCState
-BranchDispCondOp::branchTarget(const PowerISA::PCState &pc) const
+BranchDispCondOp::branchTarget(ThreadContext *tc) const
 {
+    Msr msr = tc->readMiscReg(MISCREG_MSR);
+    Addr addr;
+
     if (aaSet) {
-        return disp;
+        addr = disp;
     } else {
-        return pc.pc() + disp;
+        addr = tc->pcState().pc() + disp;
     }
+
+    return msr.sf ? addr : addr & UINT32_MAX;
 }
 
 
@@ -143,8 +153,9 @@ BranchDispCondOp::generateDisassembly(
 PowerISA::PCState
 BranchRegCondOp::branchTarget(ThreadContext *tc) const
 {
-    Addr addr = tc->readIntReg(srcRegIdx(_numSrcRegs - 1).index());
-    return addr & -4ULL;
+    Msr msr = tc->readMiscReg(MISCREG_MSR);
+    Addr addr = tc->readIntReg(srcRegIdx(_numSrcRegs - 1).index()) & -4ULL;
+    return msr.sf ? addr : addr & UINT32_MAX;
 }
 
 
index 8c311a2e3dd3732629790c6e91c121f5cd773c8b..40555aaac7cd98d3c2cec5477b14dfe2c6cc6e5b 100644 (file)
@@ -84,7 +84,7 @@ class BranchOp : public PCDependentDisassembly
     {
     }
 
-    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
+    PowerISA::PCState branchTarget(ThreadContext *tc) const override;
 
     /// Explicitly import the otherwise hidden branchTarget
     using StaticInst::branchTarget;
@@ -163,7 +163,7 @@ class BranchDispCondOp : public BranchCondOp
     {
     }
 
-    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
+    PowerISA::PCState branchTarget(ThreadContext *tc) const override;
 
     /// Explicitly import the otherwise hidden branchTarget
     using StaticInst::branchTarget;
index b107cb34a3348605e4d7d5b1b0564019ee9c674c..29f1df3b94e10d3073f88eee145126f3aa0e4b81 100644 (file)
@@ -125,10 +125,12 @@ let {{
 
 # Check the condition register (CR) allows the branch to be taken.
 def GetCondCode(br_code):
-    cond_code =  'if (checkCond(CR)) {\n'
+    cond_code =  'Msr msr = MSR;\n'
+    cond_code += 'if (checkCond(CR)) {\n'
     cond_code += '    ' + br_code + '\n'
+    cond_code += '    NIA = msr.sf ? NIA : NIA & UINT32_MAX;\n'
     cond_code += '} else {\n'
-    cond_code += '    NIA = NIA;\n'
+    cond_code += '    NIA = msr.sf ? NIA : NIA & UINT32_MAX;\n'
     cond_code += '}\n'
     return cond_code
 
@@ -139,10 +141,12 @@ def GetCtrCondCode(br_code):
     cond_code =  'uint64_t ctr = CTR;\n'
     cond_code += 'bool ctrOk = checkCtr(ctr);\n'
     cond_code += 'bool condOk = checkCond(CR);\n'
+    cond_code += 'Msr msr = MSR;\n'
     cond_code += 'if (ctrOk && condOk) {\n'
     cond_code += '    ' + br_code + '\n'
+    cond_code += '    NIA = msr.sf ? NIA : NIA & UINT32_MAX;\n'
     cond_code += '} else {\n'
-    cond_code += '    NIA = NIA;\n'
+    cond_code += '    NIA = msr.sf ? NIA : NIA & UINT32_MAX;\n'
     cond_code += '}\n'
     cond_code += 'CTR = ctr;\n'
     return cond_code
index 3ab9ad9236fdc6ffbbb48615439af144390b9930..5a353d0ae2085b71e3a56c6435b48cd229e6c7a8 100644 (file)
@@ -76,38 +76,60 @@ readXERCode = 'M5_VAR_USED Xer xer = XER;'
 setXERCode = 'XER = xer;'
 
 computeCR0Code = '''
+{
     Cr cr = CR;
-    cr.cr0 = makeCRField((int64_t)%(result)s, (int64_t)0, xer.so);
+    Msr msr = MSR;
+    cr.cr0 = msr.sf ?
+             makeCRField((int64_t)%(result)s, (int64_t)0, xer.so) :
+             makeCRField((int32_t)%(result)s, (int32_t)0, xer.so);
     CR = cr;
+}
 '''
 
 computeCACode = '''
-    if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) {
+{
+    Msr msr = MSR;
+    if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) {
         xer.ca = 1;
+        xer.ca32 = 1;
     } else {
         xer.ca = 0;
+        xer.ca32 = 0;
     }
 
-    if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) {
-        xer.ca32 = 1;
-    } else {
-        xer.ca32 = 0;
+    if (msr.sf) {
+        if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) {
+            xer.ca = 1;
+        } else {
+            xer.ca = 0;
+        }
     }
+}
 '''
 
 computeOVCode = '''
-    if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) {
+{
+    Msr msr = MSR;
+    if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
         xer.ov = 1;
-        xer.so = 1;
+        xer.ov32 = 1;
     } else {
         xer.ov = 0;
+        xer.ov32 = 0;
     }
 
-    if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
-        xer.ov32 = 1;
-    } else {
-        xer.ov32 = 0;
+    if (msr.sf) {
+        if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) {
+            xer.ov = 1;
+        } else {
+            xer.ov = 0;
+        }
+    }
+
+    if (xer.ov) {
+        xer.so = 1;
     }
+}
 '''
 
 setCACode = '''
index 1cddc409af46f4439f92f36bddc7a9d73ab44bd9..743ac61231042eed237af7c21e0ecb5200438ad6 100644 (file)
@@ -68,13 +68,16 @@ def template LoadExecute {{
     {
         Addr EA;
         Fault fault = NoFault;
+        Msr msr = xc->readMiscReg(MISCREG_MSR);
 
         %(op_decl)s;
         %(op_rd)s;
         %(ea_code)s;
 
         if (fault == NoFault) {
-            fault = readMemAtomicBE(xc, traceData, EA, Mem, memAccessFlags);
+            fault = msr.le ?
+                    readMemAtomicLE(xc, traceData, EA, Mem, memAccessFlags) :
+                    readMemAtomicBE(xc, traceData, EA, Mem, memAccessFlags);
             %(memacc_code)s;
         }
 
@@ -114,13 +117,17 @@ def template LoadCompleteAcc {{
     {
         M5_VAR_USED Addr EA;
         Fault fault = NoFault;
+        Msr msr = xc->readMiscReg(MISCREG_MSR);
 
         %(op_decl)s;
         %(op_rd)s;
 
         EA = pkt->req->getVaddr();
 
-        getMemBE(pkt, Mem, traceData);
+        if (msr.le)
+            getMemLE(pkt, Mem, traceData);
+        else
+            getMemBE(pkt, Mem, traceData);
 
         if (fault == NoFault) {
             %(memacc_code)s;
@@ -141,6 +148,7 @@ def template StoreExecute {{
     {
         Addr EA;
         Fault fault = NoFault;
+        Msr msr = xc->readMiscReg(MISCREG_MSR);
 
         %(op_decl)s;
         %(op_rd)s;
@@ -151,8 +159,11 @@ def template StoreExecute {{
         }
 
         if (fault == NoFault) {
-            fault = writeMemAtomicBE(xc, traceData, Mem, EA, memAccessFlags,
-                    NULL);
+            fault = msr.le ?
+                    writeMemAtomicLE(xc, traceData, Mem, EA, memAccessFlags,
+                                     NULL) :
+                    writeMemAtomicBE(xc, traceData, Mem, EA, memAccessFlags,
+                                     NULL);
         }
 
         if (fault == NoFault) {
@@ -170,6 +181,7 @@ def template StoreInitiateAcc {{
     {
         Addr EA;
         Fault fault = NoFault;
+        Msr msr = xc->readMiscReg(MISCREG_MSR);
 
         %(op_decl)s;
         %(op_rd)s;
@@ -180,8 +192,11 @@ def template StoreInitiateAcc {{
         }
 
         if (fault == NoFault) {
-            fault = writeMemTimingBE(xc, traceData, Mem, EA, memAccessFlags,
-                    NULL);
+            fault = msr.le ?
+                    writeMemTimingLE(xc, traceData, Mem, EA, memAccessFlags,
+                                     NULL) :
+                    writeMemTimingBE(xc, traceData, Mem, EA, memAccessFlags,
+                                     NULL);
         }
 
         // Need to write back any potential address register update
index bdd59484367ec55e325fe3a13965636202ddf809..2b4fb27bfd518379dd750b930b9fefee9e1ddd74 100644 (file)
@@ -67,6 +67,7 @@ def operands {{
     'LR': ('ControlReg', 'ud', 'MISCREG_LR', 'IsInteger', 9),
     'CTR': ('ControlReg', 'ud', 'MISCREG_CTR', 'IsInteger', 9),
     'TAR': ('ControlReg', 'ud', 'MISCREG_TAR', 'IsInteger', 9),
+    'MSR': ('ControlReg', 'ud', 'MISCREG_MSR', 'IsInteger', 9),
 
     # Setting as ControlReg so things are stored as an integer, not double
     'FPSCR': ('ControlReg', 'uw', 'MISCREG_FPSCR', 'IsFloating', 9),
index 1c9746b906f6bf1326a482158ccffba222cbe260..1eae968197ed620f31bb465f0e7ee636428a845e 100644 (file)
@@ -41,6 +41,7 @@ enum MiscRegIndex {
     MISCREG_LR,
     MISCREG_CTR,
     MISCREG_TAR,
+    MISCREG_MSR,
     NUM_MISCREGS
 };
 
@@ -50,7 +51,8 @@ const char * const miscRegName[NUM_MISCREGS] = {
     "XER",
     "LR",
     "CTR",
-    "TAR"
+    "TAR",
+    "MSR"
 };
 
 BitUnion32(Cr)
@@ -107,6 +109,26 @@ BitUnion32(Fpscr)
     Bitfield<2,1> rn;
 EndBitUnion(Fpscr)
 
+BitUnion64(Msr)
+    Bitfield<63> sf;
+    Bitfield<60> hv;
+    Bitfield<34, 33> ts;
+    Bitfield<32> tm;
+    Bitfield<25> vec;
+    Bitfield<23> vsx;
+    Bitfield<15> ee;
+    Bitfield<14> pr;
+    Bitfield<13> fp;
+    Bitfield<12> me;
+    Bitfield<11> fe0;
+    Bitfield<10, 9> te;
+    Bitfield<8> fe1;
+    Bitfield<5> ir;
+    Bitfield<4> dr;
+    Bitfield<2> pmm;
+    Bitfield<1> ri;
+    Bitfield<0> le;
+EndBitUnion(Msr)
 } // namespace PowerISA
 
 #endif // __ARCH_POWER_MISCREGS_HH__
index c81d12ec5a8c603a24a1db2e6946c316903b6810..409f980ae55370c32419694917d0ab75bb3b3b5e 100644 (file)
@@ -274,6 +274,19 @@ PowerProcess::argsInit(int pageSize)
     //Set the stack pointer register
     tc->setIntReg(StackPointerReg, stack_min);
 
+    //Set the machine status for a typical userspace
+    Msr msr = 0;
+    msr.sf = (intSize == 8);
+    msr.hv = 1;
+    msr.ee = 1;
+    msr.pr = 1;
+    msr.me = 1;
+    msr.ir = 1;
+    msr.dr = 1;
+    msr.ri = 1;
+    msr.le = (byteOrder == ByteOrder::little);
+    tc->setMiscReg(MISCREG_MSR, msr);
+
     tc->pcState(getStartPC());
 
     //Align the "stack_min" to a page boundary.