SPARC: Make software trap 3 flush the register windows like the ABI specifies.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 4 Oct 2007 19:24:16 +0000 (12:24 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 4 Oct 2007 19:24:16 +0000 (12:24 -0700)
--HG--
extra : convert_revision : 8ff43617b56dcca5783d6cc490f87140fc20a36d

src/arch/sparc/process.cc
src/arch/sparc/process.hh
src/arch/sparc/solaris/process.cc
src/arch/sparc/solaris/process.hh

index 29b1a244bdf434cf545b9b8618171cf68d8818a1..91564e754d107fa87aa6dd5d0719a95e40639631 100644 (file)
@@ -73,8 +73,39 @@ void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
 {
     switch(trapNum)
     {
+      case 0x01: //Software breakpoint
+        warn("Software breakpoint encountered at pc %#x.\n", tc->readPC());
+        break;
+      case 0x02: //Division by zero
+        warn("Software signaled a division by zero at pc %#x.\n",
+                tc->readPC());
+        break;
       case 0x03: //Flush window trap
-        warn("Ignoring request to flush register windows.\n");
+        flushWindows(tc);
+        break;
+      case 0x04: //Clean windows
+        warn("Ignoring process request for clean register "
+                "windows at pc %#x.\n", tc->readPC());
+        break;
+      case 0x05: //Range check
+        warn("Software signaled a range check at pc %#x.\n",
+                tc->readPC());
+        break;
+      case 0x06: //Fix alignment
+        warn("Ignoring process request for os assisted unaligned accesses "
+                "at pc %#x.\n", tc->readPC());
+        break;
+      case 0x07: //Integer overflow
+        warn("Software signaled an integer overflow at pc %#x.\n",
+                tc->readPC());
+        break;
+      case 0x32: //Get integer condition codes
+        warn("Ignoring process request to get the integer condition codes "
+                "at pc %#x.\n", tc->readPC());
+        break;
+      case 0x33: //Set integer condition codes
+        warn("Ignoring process request to set the integer condition codes "
+                "at pc %#x.\n", tc->readPC());
         break;
       default:
         panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum);
@@ -636,3 +667,73 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
 
 //    num_processes++;
 }
+
+void Sparc32LiveProcess::flushWindows(ThreadContext *tc)
+{
+    IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);
+    IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4);
+    IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6);
+    MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
+    MiscReg origCWP = CWP;
+    CWP = (CWP + Cansave + 2) % NWindows;
+    while(NWindows - 2 - Cansave != 0)
+    {
+        if (Otherwin) {
+            panic("Otherwin non-zero.\n");
+        } else {
+            tc->setMiscReg(MISCREG_CWP, CWP);
+            //Do the stores
+            IntReg sp = tc->readIntReg(StackPointerReg);
+            for (int index = 16; index < 32; index++) {
+                IntReg regVal = tc->readIntReg(index);
+                regVal = htog(regVal);
+                if (!tc->getMemPort()->tryWriteBlob(
+                        sp + (index - 16) * 4, (uint8_t *)&regVal, 4)) {
+                    warn("Failed to save register to the stack when "
+                            "flushing windows.\n");
+                }
+            }
+            Canrestore--;
+            Cansave++;
+            CWP = (CWP + 1) % NWindows;
+        }
+    }
+    tc->setIntReg(NumIntArchRegs + 3, Cansave);
+    tc->setIntReg(NumIntArchRegs + 4, Canrestore);
+    tc->setMiscReg(MISCREG_CWP, origCWP);
+}
+
+void Sparc64LiveProcess::flushWindows(ThreadContext *tc)
+{
+    IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);
+    IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4);
+    IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6);
+    MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
+    MiscReg origCWP = CWP;
+    CWP = (CWP + Cansave + 2) % NWindows;
+    while(NWindows - 2 - Cansave != 0)
+    {
+        if (Otherwin) {
+            panic("Otherwin non-zero.\n");
+        } else {
+            tc->setMiscReg(MISCREG_CWP, CWP);
+            //Do the stores
+            IntReg sp = tc->readIntReg(StackPointerReg);
+            for (int index = 16; index < 32; index++) {
+                IntReg regVal = tc->readIntReg(index);
+                regVal = htog(regVal);
+                if (!tc->getMemPort()->tryWriteBlob(
+                        sp + 2047 + (index - 16) * 8, (uint8_t *)&regVal, 8)) {
+                    warn("Failed to save register to the stack when "
+                            "flushing windows.\n");
+                }
+            }
+            Canrestore--;
+            Cansave++;
+            CWP = (CWP + 1) % NWindows;
+        }
+    }
+    tc->setIntReg(NumIntArchRegs + 3, Cansave);
+    tc->setIntReg(NumIntArchRegs + 4, Canrestore);
+    tc->setMiscReg(MISCREG_CWP, origCWP);
+}
index 2512441c61f9aa41e727439d3e4bba7f6a0d606b..f4e823a9a799fbf5f8b85d0770750adef107bdc1 100644 (file)
@@ -66,6 +66,7 @@ class SparcLiveProcess : public LiveProcess
     Addr readSpillStart()
     { return spillStart; }
 
+    virtual void flushWindows(ThreadContext *tc) = 0;
 };
 
 struct M5_32_auxv_t
@@ -116,6 +117,7 @@ class Sparc32LiveProcess : public SparcLiveProcess
 
     void argsInit(int intSize, int pageSize);
 
+    void flushWindows(ThreadContext *tc);
 };
 
 struct M5_64_auxv_t
@@ -169,6 +171,7 @@ class Sparc64LiveProcess : public SparcLiveProcess
 
     void argsInit(int intSize, int pageSize);
 
+    void flushWindows(ThreadContext *tc);
 };
 
 #endif // __SPARC_PROCESS_HH__
index f9876bf00d265b06bee8bae3676dcc84b432f08b..b7a49ab8d4355e025e72b818da3d3a179da6db54 100644 (file)
@@ -336,7 +336,7 @@ SparcSolarisProcess::SparcSolarisProcess(const std::string &name,
                                      uint64_t _egid,
                                      uint64_t _pid,
                                      uint64_t _ppid)
-    : SparcLiveProcess(name, objFile, system,
+    : Sparc64LiveProcess(name, objFile, system,
             stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd,
             _uid, _euid, _gid, _egid, _pid, _ppid),
      Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
index f65a60656617aa703fc6de9f04502441327b391a..174eaecd7ff857f6d12a7113e651b9dd7314711a 100644 (file)
@@ -38,7 +38,7 @@
 namespace SparcISA {
 
 /// A process with emulated SPARC/Solaris syscalls.
-class SparcSolarisProcess : public SparcLiveProcess
+class SparcSolarisProcess : public Sparc64LiveProcess
 {
   public:
     /// Constructor.
@@ -66,4 +66,4 @@ class SparcSolarisProcess : public SparcLiveProcess
 
 
 } // namespace SparcISA
-#endif // __ALPHA_SOLARIS_PROCESS_HH__
+#endif // __SPARC_SOLARIS_PROCESS_HH__