Move the SyscallReturn class into sim/syscallreturn.hh. Also move some miscregs into...
authorGabe Black <gblack@eecs.umich.edu>
Tue, 5 Dec 2006 06:55:02 +0000 (01:55 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Tue, 5 Dec 2006 06:55:02 +0000 (01:55 -0500)
src/arch/alpha/syscallreturn.hh:
src/arch/mips/syscallreturn.hh:
src/sim/syscallreturn.hh:
    Move the SyscallReturn class into sim/syscallreturn.hh
src/arch/sparc/faults.cc:
src/arch/sparc/isa/operands.isa:
src/arch/sparc/isa_traits.hh:
src/arch/sparc/miscregfile.cc:
src/arch/sparc/miscregfile.hh:
src/arch/sparc/process.cc:
src/arch/sparc/sparc_traits.hh:
    Move some miscregs into the integer register file so they get renamed.

--HG--
extra : convert_revision : df5b94fa1e7fdca34816084e0a423d6fdf86c79b

src/arch/alpha/syscallreturn.hh
src/arch/mips/syscallreturn.hh
src/arch/sparc/faults.cc
src/arch/sparc/isa/operands.isa
src/arch/sparc/isa_traits.hh
src/arch/sparc/miscregfile.cc
src/arch/sparc/miscregfile.hh
src/arch/sparc/process.cc
src/arch/sparc/sparc_traits.hh
src/arch/sparc/syscallreturn.hh
src/sim/syscallreturn.hh [new file with mode: 0644]

index 803c3b7da690f96c66c7eb997e52f481d5515b5c..88a6bf4997692e10c1122d899a2e395190605d1c 100644 (file)
 #ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__
 #define __ARCH_ALPHA_SYSCALLRETURN_HH__
 
-class SyscallReturn {
-    public:
-       template <class T>
-       SyscallReturn(T v, bool s)
-       {
-           retval = (uint64_t)v;
-           success = s;
-       }
-
-       template <class T>
-       SyscallReturn(T v)
-       {
-           success = (v >= 0);
-           retval = (uint64_t)v;
-       }
-
-       ~SyscallReturn() {}
-
-       SyscallReturn& operator=(const SyscallReturn& s) {
-           retval = s.retval;
-           success = s.success;
-           return *this;
-       }
-
-       bool successful() { return success; }
-       uint64_t value() { return retval; }
-
-
-   private:
-       uint64_t retval;
-       bool success;
-};
+#include "sim/syscallreturn.hh"
 
 namespace AlphaISA
 {
index ef1093caf652654ebc9fab197597f93d9dc0ef0d..0d36b333037f55478861dd366cd7e27a836e9066 100644 (file)
 #ifndef __ARCH_MIPS_SYSCALLRETURN_HH__
 #define __ARCH_MIPS_SYSCALLRETURN_HH__
 
-class SyscallReturn {
-        public:
-           template <class T>
-           SyscallReturn(T v, bool s)
-           {
-               retval = (uint32_t)v;
-               success = s;
-           }
-
-           template <class T>
-           SyscallReturn(T v)
-           {
-               success = (v >= 0);
-               retval = (uint32_t)v;
-           }
-
-           ~SyscallReturn() {}
-
-           SyscallReturn& operator=(const SyscallReturn& s) {
-               retval = s.retval;
-               success = s.success;
-               return *this;
-           }
-
-           bool successful() { return success; }
-           uint64_t value() { return retval; }
-
-
-       private:
-           uint64_t retval;
-           bool success;
-};
+#include "sim/syscallreturn.hh"
 
 namespace MipsISA
 {
index 9a29f24d56a627e374de7fdf477f94dcaa911263..67920a3d18ec239afeb0e8a1d642c2be5d7212ac 100644 (file)
@@ -302,10 +302,12 @@ void doREDFault(ThreadContext *tc, TrapType tt)
     MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE);
     MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
     MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
-    MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
+    //MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
+    MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
     MiscReg ASI = tc->readMiscReg(MISCREG_ASI);
     MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
-    MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
+    //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
+    MiscReg CANSAVE = tc->readMiscReg(NumIntArchRegs + 3);
     MiscReg GL = tc->readMiscReg(MISCREG_GL);
     MiscReg PC = tc->readPC();
     MiscReg NPC = tc->readNextPC();
@@ -396,10 +398,12 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
     MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE);
     MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
     MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
-    MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
+    //MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
+    MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
     MiscReg ASI = tc->readMiscReg(MISCREG_ASI);
     MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
-    MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
+    //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
+    MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3);
     MiscReg GL = tc->readMiscReg(MISCREG_GL);
     MiscReg PC = tc->readPC();
     MiscReg NPC = tc->readNextPC();
index 80ed7362cb9be17114dbe9b884a0047b57d57d22..9a5fda6ffc9deef64c429996380a4c39f927d9b9 100644 (file)
@@ -56,12 +56,23 @@ def operands {{
     # Int regs default to unsigned, but code should not count on this.
     # For clarity, descriptions that depend on unsigned behavior should
     # explicitly specify '.uq'.
+
     'Rd':              ('IntReg', 'udw', 'RD', 'IsInteger', 1),
-    'RdLow':           ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2),
-    'RdHigh':          ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
-    'Rs1':             ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
-    'Rs2':             ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
-    'uReg0':           ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 6),
+    # The Rd from the previous window
+    'Rd_prev':         ('IntReg', 'udw', 'RD + NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 2),
+    # The Rd from the next window
+    'Rd_next':         ('IntReg', 'udw', 'RD + 2 * NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 3),
+    # The low (even) register of a two register pair
+    'RdLow':           ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 4),
+    # The high (odd) register of a two register pair
+    'RdHigh':          ('IntReg', 'udw', 'RD | 1', 'IsInteger', 5),
+    'Rs1':             ('IntReg', 'udw', 'RS1', 'IsInteger', 6),
+    'Rs2':             ('IntReg', 'udw', 'RS2', 'IsInteger', 7),
+    # A microcode register. Right now, this is the only one.
+    'uReg0':           ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 8),
+    # Because double and quad precision register numbers are decoded
+    # differently, they get different operands. The single precision versions
+    # have an s post pended to their name.
     'Frds':            ('FloatReg', 'sf', 'RD', 'IsFloating', 10),
     'Frd':             ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
     # Each Frd_N refers to the Nth double precision register from Frd.
@@ -80,14 +91,17 @@ def operands {{
     'Frs2':            ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
     'NPC':             ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
     'NNPC':            ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
+    # Registers which are used explicitly in instructions
     'R0':              ('IntReg', 'udw', '0', None, 6),
     'R1':              ('IntReg', 'udw', '1', None, 7),
     'R15':             ('IntReg', 'udw', '15', 'IsInteger', 8),
     'R16':             ('IntReg', 'udw', '16', None, 9),
 
     # Control registers
-    'Y':               ('ControlReg', 'udw', 'MISCREG_Y', None, 40),
-    'Ccr':             ('ControlReg', 'udw', 'MISCREG_CCR', None, 41),
+#   'Y':               ('ControlReg', 'udw', 'MISCREG_Y', None, 40),
+#   'Ccr':             ('ControlReg', 'udw', 'MISCREG_CCR', None, 41),
+    'Y':               ('IntReg', 'udw', 'NumIntArchRegs + 1', None, 40),
+    'Ccr':             ('IntReg', 'udw', 'NumIntArchRegs + 2', None, 41),
     'Asi':             ('ControlReg', 'udw', 'MISCREG_ASI', None, 42),
     'Fprs':            ('ControlReg', 'udw', 'MISCREG_FPRS', None, 43),
     'Pcr':             ('ControlReg', 'udw', 'MISCREG_PCR', None, 44),
@@ -109,12 +123,17 @@ def operands {{
     'Pstate':          ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59),
     'Tl':              ('ControlReg', 'udw', 'MISCREG_TL', None, 60),
     'Pil':             ('ControlReg', 'udw', 'MISCREG_PIL', None, 61),
-    'Cwp':             ('ControlReg', 'udw', 'MISCREG_CWP', None, 62),
-    'Cansave':         ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63),
-    'Canrestore':      ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64),
-    'Cleanwin':                ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65),
-    'Otherwin':                ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66),
-    'Wstate':          ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67),
+    'Cwp':             ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing']), 62),
+#   'Cansave':         ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63),
+#   'Canrestore':      ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64),
+#   'Cleanwin':                ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65),
+#   'Otherwin':                ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66),
+#   'Wstate':          ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67),
+    'Cansave':         ('IntReg', 'udw', 'NumIntArchRegs + 3', None, 63),
+    'Canrestore':      ('IntReg', 'udw', 'NumIntArchRegs + 4', None, 64),
+    'Cleanwin':                ('IntReg', 'udw', 'NumIntArchRegs + 5', None, 65),
+    'Otherwin':                ('IntReg', 'udw', 'NumIntArchRegs + 6', None, 66),
+    'Wstate':          ('IntReg', 'udw', 'NumIntArchRegs + 7', None, 67),
     'Gl':               ('ControlReg', 'udw', 'MISCREG_GL', None, 68),
 
     'Hpstate':         ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69),
index 287f9065885e09a4e7b7e51f9f327c25eaf3726d..7d786dc3bdcabf76a534ed1c4846ab8f284e0264 100644 (file)
@@ -58,8 +58,8 @@ namespace SparcISA
 
     // These enumerate all the registers for dependence tracking.
     enum DependenceTags {
-        FP_Base_DepTag = 33,
-        Ctrl_Base_DepTag = 97,
+        FP_Base_DepTag = 32*3+8,
+        Ctrl_Base_DepTag = FP_Base_DepTag + 64,
     };
 
     // semantically meaningful register indices
index 7b0939c290d71397d84d1a8f4d5dd4654385d647..50a4f487103d59b4ca3165d16812d7d562dd9e85 100644 (file)
@@ -50,12 +50,12 @@ class Checkpoint;
 string SparcISA::getMiscRegName(RegIndex index)
 {
     static::string miscRegName[NumMiscRegs] =
-        {"y", "ccr", "asi", "tick", "fprs", "pcr", "pic",
+        {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic",
          "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
          "stick", "stick_cmpr",
          "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
-         "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
-         "wstate", "gl",
+         "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin",
+         "wstate",*/ "gl",
          "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
          "hstick_cmpr",
          "fsr"};
@@ -109,10 +109,10 @@ void MiscRegFile::clear()
 MiscReg MiscRegFile::readReg(int miscReg)
 {
     switch (miscReg) {
-        case MISCREG_Y:
-          return y;
-        case MISCREG_CCR:
-          return ccr;
+//        case MISCREG_Y:
+//          return y;
+//        case MISCREG_CCR:
+//          return ccr;
         case MISCREG_ASI:
           return asi;
         case MISCREG_FPRS:
@@ -155,16 +155,16 @@ MiscReg MiscRegFile::readReg(int miscReg)
           return pil;
         case MISCREG_CWP:
           return cwp;
-        case MISCREG_CANSAVE:
-          return cansave;
-        case MISCREG_CANRESTORE:
-          return canrestore;
-        case MISCREG_CLEANWIN:
-          return cleanwin;
-        case MISCREG_OTHERWIN:
-          return otherwin;
-        case MISCREG_WSTATE:
-          return wstate;
+//        case MISCREG_CANSAVE:
+//          return cansave;
+//        case MISCREG_CANRESTORE:
+//          return canrestore;
+//        case MISCREG_CLEANWIN:
+//          return cleanwin;
+//        case MISCREG_OTHERWIN:
+//          return otherwin;
+//        case MISCREG_WSTATE:
+//          return wstate;
         case MISCREG_GL:
           return gl;
 
@@ -225,12 +225,12 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
 void MiscRegFile::setReg(int miscReg, const MiscReg &val)
 {
     switch (miscReg) {
-        case MISCREG_Y:
-          y = val;
-          break;
-        case MISCREG_CCR:
-          ccr = val;
-          break;
+//        case MISCREG_Y:
+//          y = val;
+//       break;
+//        case MISCREG_CCR:
+//          ccr = val;
+//       break;
         case MISCREG_ASI:
           asi = val;
           break;
@@ -291,21 +291,21 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
         case MISCREG_CWP:
           cwp = val;
           break;
-        case MISCREG_CANSAVE:
-          cansave = val;
-          break;
-        case MISCREG_CANRESTORE:
-          canrestore = val;
-          break;
-        case MISCREG_CLEANWIN:
-          cleanwin = val;
-          break;
-        case MISCREG_OTHERWIN:
-          otherwin = val;
-          break;
-        case MISCREG_WSTATE:
-          wstate = val;
-          break;
+//        case MISCREG_CANSAVE:
+//          cansave = val;
+//       break;
+//        case MISCREG_CANRESTORE:
+//          canrestore = val;
+//       break;
+//        case MISCREG_CLEANWIN:
+//          cleanwin = val;
+//       break;
+//        case MISCREG_OTHERWIN:
+//          otherwin = val;
+//       break;
+//        case MISCREG_WSTATE:
+//          wstate = val;
+//       break;
         case MISCREG_GL:
           gl = val;
           break;
index 6bc04b5839384311734e94db21ef3c7d645675c7..cf0405ac4c48795ad1d2fb1a7b2de1788a6bfedc 100644 (file)
@@ -48,8 +48,8 @@ namespace SparcISA
     enum MiscRegIndex
     {
         /** Ancillary State Registers */
-        MISCREG_Y,
-        MISCREG_CCR,
+//        MISCREG_Y,
+//        MISCREG_CCR,
         MISCREG_ASI,
         MISCREG_TICK,
         MISCREG_FPRS,
@@ -74,11 +74,11 @@ namespace SparcISA
         MISCREG_TL,
         MISCREG_PIL,
         MISCREG_CWP,
-        MISCREG_CANSAVE,
-        MISCREG_CANRESTORE,
-        MISCREG_CLEANWIN,
-        MISCREG_OTHERWIN,
-        MISCREG_WSTATE,
+//        MISCREG_CANSAVE,
+//        MISCREG_CANRESTORE,
+//        MISCREG_CLEANWIN,
+//        MISCREG_OTHERWIN,
+//        MISCREG_WSTATE,
         MISCREG_GL,
 
         /** Hyper privileged registers */
index 405e408e5adb94caf6c3c1c4c7b8613d477bb79f..073117a841ecaa2918165d80ba4e5fc9e91b5eec 100644 (file)
@@ -95,17 +95,22 @@ SparcLiveProcess::startup()
      */
 
     //No windows contain info from other programs
-    threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0);
+    //threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0);
+    threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
     //There are no windows to pop
-    threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0);
+    //threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0);
+    threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
     //All windows are available to save into
-    threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2);
+    //threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2);
+    threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
     //All windows are "clean"
-    threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows);
+    //threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows);
+    threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
     //Start with register window 0
     threadContexts[0]->setMiscReg(MISCREG_CWP, 0);
     //Always use spill and fill traps 0
-    threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
+    //threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
+    threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
     //Set the trap level to 0
     threadContexts[0]->setMiscReg(MISCREG_TL, 0);
     //Set the ASI register to something fixed
index a3d29ea8a1d60f5a5a3ac61d0579048e60a00506..d89ec11198a8f3a7ef1d481a34cd06d030f9ac3f 100644 (file)
@@ -41,7 +41,8 @@ namespace SparcISA
 
     // Number of register windows, can legally be 3 to 32
     const int NWindows = 8;
-    const int NumMicroIntRegs = 1;
+    //const int NumMicroIntRegs = 1;
+    const int NumMicroIntRegs = 8;
 
 //    const int NumRegularIntRegs = MaxGL * 8 + NWindows * 16;
 //    const int NumMicroIntRegs = 1;
index 75a063da16fb4d404cfe80c0742184722c7de891..c2494c3648e75ce4a7632905814fbc3f3b6746ca 100644 (file)
 
 #include <inttypes.h>
 
+#include "sim/syscallreturn.hh"
 #include "arch/sparc/regfile.hh"
-
-class SyscallReturn
-{
-  public:
-    template <class T>
-    SyscallReturn(T v, bool s)
-    {
-        retval = (uint64_t)v;
-        success = s;
-    }
-
-    template <class T>
-    SyscallReturn(T v)
-    {
-        success = (v >= 0);
-        retval = (uint64_t)v;
-    }
-
-    ~SyscallReturn() {}
-
-    SyscallReturn& operator=(const SyscallReturn& s)
-    {
-        retval = s.retval;
-        success = s.success;
-        return *this;
-    }
-
-    bool successful() { return success; }
-    uint64_t value() { return retval; }
-
-    private:
-    uint64_t retval;
-    bool success;
-};
+#include "cpu/thread_context.hh"
 
 namespace SparcISA
 {
     static inline void setSyscallReturn(SyscallReturn return_value,
-            RegFile *regs)
+            ThreadContext * tc)
     {
         // check for error condition.  SPARC syscall convention is to
         // indicate success/failure in reg the carry bit of the ccr
         // and put the return value itself in the standard return value reg ().
         if (return_value.successful()) {
             // no error, clear XCC.C
-            regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEE);
-            regs->setIntReg(ReturnValueReg, return_value.value());
+            tc->setIntReg(NumIntArchRegs + 2,
+                    tc->readIntReg(NumIntArchRegs + 2) & 0xEE);
+            //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) & 0xEE);
+            tc->setIntReg(ReturnValueReg, return_value.value());
         } else {
             // got an error, set XCC.C
-            regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x11);
-            regs->setIntReg(ReturnValueReg, return_value.value());
+            tc->setIntReg(NumIntArchRegs + 2,
+                    tc->readIntReg(NumIntArchRegs + 2) | 0x11);
+            //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) | 0x11);
+            tc->setIntReg(ReturnValueReg, return_value.value());
         }
     }
 };
diff --git a/src/sim/syscallreturn.hh b/src/sim/syscallreturn.hh
new file mode 100644 (file)
index 0000000..d1c43f5
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __SIM_SYSCALLRETURN_HH__
+#define __SIM_SYSCALLRETURN_HH__
+
+#include <inttypes.h>
+
+class SyscallReturn
+{
+  public:
+    template <class T>
+    SyscallReturn(T v, bool s)
+    {
+        retval = (uint64_t)v;
+        success = s;
+    }
+
+    template <class T>
+    SyscallReturn(T v)
+    {
+        success = (v >= 0);
+        retval = (uint64_t)v;
+    }
+
+    ~SyscallReturn() {}
+
+    SyscallReturn& operator=(const SyscallReturn& s)
+    {
+        retval = s.retval;
+        success = s.success;
+        return *this;
+    }
+
+    bool successful() { return success; }
+    uint64_t value() { return retval; }
+
+    private:
+    uint64_t retval;
+    bool success;
+};
+
+#endif