X86: Define a noop ExtMachInst.
[gem5.git] / src / arch / sparc / process.cc
index 6e490e05eb8ac6919e098e28f9b5fa7370fde73f..0cd8889a988f23b6611f535c5cd4ea2cda4851fe 100644 (file)
@@ -32,6 +32,7 @@
 #include "arch/sparc/asi.hh"
 #include "arch/sparc/handlers.hh"
 #include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/registers.hh"
 #include "arch/sparc/process.hh"
 #include "arch/sparc/types.hh"
 #include "base/loader/object_file.hh"
@@ -46,6 +47,8 @@
 using namespace std;
 using namespace SparcISA;
 
+static const int FirstArgumentReg = 8;
+
 
 SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params,
         ObjectFile *objFile, Addr _StackBias)
@@ -108,74 +111,71 @@ void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
 }
 
 void
-SparcLiveProcess::startup()
+SparcLiveProcess::initState()
 {
-    Process::startup();
+    LiveProcess::initState();
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //From the SPARC ABI
 
     //Setup default FP state
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
+    tc->setMiscRegNoEffect(MISCREG_FSR, 0);
 
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
+    tc->setMiscRegNoEffect(MISCREG_TICK, 0);
 
     /*
      * Register window management registers
      */
 
     //No windows contain info from other programs
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
+    //tc->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
+    tc->setIntReg(NumIntArchRegs + 6, 0);
     //There are no windows to pop
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
+    //tc->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
+    tc->setIntReg(NumIntArchRegs + 4, 0);
     //All windows are available to save into
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
+    //tc->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
+    tc->setIntReg(NumIntArchRegs + 3, NWindows - 2);
     //All windows are "clean"
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
+    //tc->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
+    tc->setIntReg(NumIntArchRegs + 5, NWindows);
     //Start with register window 0
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
+    tc->setMiscReg(MISCREG_CWP, 0);
     //Always use spill and fill traps 0
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
+    //tc->setMiscRegNoEffect(MISCREG_WSTATE, 0);
+    tc->setIntReg(NumIntArchRegs + 7, 0);
     //Set the trap level to 0
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
+    tc->setMiscRegNoEffect(MISCREG_TL, 0);
     //Set the ASI register to something fixed
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
+    tc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
 
     /*
      * T1 specific registers
      */
     //Turn on the icache, dcache, dtb translation, and itb translation.
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
+    tc->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
 }
 
 void
-Sparc32LiveProcess::startup()
+Sparc32LiveProcess::initState()
 {
-    if (checkpointRestored)
-        return;
-
-    SparcLiveProcess::startup();
+    SparcLiveProcess::initState();
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //The process runs in user mode with 32 bit addresses
-    threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
+    tc->setMiscReg(MISCREG_PSTATE, 0x0a);
 
     argsInit(32 / 8, VMPageSize);
 }
 
 void
-Sparc64LiveProcess::startup()
+Sparc64LiveProcess::initState()
 {
-    if (checkpointRestored)
-        return;
-
-    SparcLiveProcess::startup();
+    SparcLiveProcess::initState();
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //The process runs in user mode
-    threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
+    tc->setMiscReg(MISCREG_PSTATE, 0x02);
 
     argsInit(sizeof(IntReg), VMPageSize);
 }
@@ -186,7 +186,7 @@ SparcLiveProcess::argsInit(int pageSize)
 {
     int intSize = sizeof(IntType);
 
-    typedef M5_auxv_t<IntType> auxv_t;
+    typedef AuxVector<IntType> auxv_t;
 
     std::vector<auxv_t> auxv;
 
@@ -335,18 +335,18 @@ SparcLiveProcess::argsInit(int pageSize)
     IntType window_save_base = argc_base - window_save_size;
 #endif
 
-    DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
-    DPRINTF(Sparc, "%#x - sentry NULL\n", sentry_base);
-    DPRINTF(Sparc, "filename = %s\n", filename);
-    DPRINTF(Sparc, "%#x - file name\n", file_name_base);
-    DPRINTF(Sparc, "%#x - env data\n", env_data_base);
-    DPRINTF(Sparc, "%#x - arg data\n", arg_data_base);
-    DPRINTF(Sparc, "%#x - auxv array\n", auxv_array_base);
-    DPRINTF(Sparc, "%#x - envp array\n", envp_array_base);
-    DPRINTF(Sparc, "%#x - argv array\n", argv_array_base);
-    DPRINTF(Sparc, "%#x - argc \n", argc_base);
-    DPRINTF(Sparc, "%#x - window save\n", window_save_base);
-    DPRINTF(Sparc, "%#x - stack min\n", stack_min);
+    DPRINTF(Stack, "The addresses of items on the initial stack:\n");
+    DPRINTF(Stack, "%#x - sentry NULL\n", sentry_base);
+    DPRINTF(Stack, "filename = %s\n", filename);
+    DPRINTF(Stack, "%#x - file name\n", file_name_base);
+    DPRINTF(Stack, "%#x - env data\n", env_data_base);
+    DPRINTF(Stack, "%#x - arg data\n", arg_data_base);
+    DPRINTF(Stack, "%#x - auxv array\n", auxv_array_base);
+    DPRINTF(Stack, "%#x - envp array\n", envp_array_base);
+    DPRINTF(Stack, "%#x - argv array\n", argv_array_base);
+    DPRINTF(Stack, "%#x - argc \n", argc_base);
+    DPRINTF(Stack, "%#x - window save\n", window_save_base);
+    DPRINTF(Stack, "%#x - stack min\n", stack_min);
 
     assert(window_save_base == stack_min);
 
@@ -354,7 +354,7 @@ SparcLiveProcess::argsInit(int pageSize)
 
     // figure out argc
     IntType argc = argv.size();
-    IntType guestArgc = TheISA::htog(argc);
+    IntType guestArgc = SparcISA::htog(argc);
 
     //Write out the sentry void *
     uint64_t sentry_NULL = 0;
@@ -391,20 +391,21 @@ SparcLiveProcess::argsInit(int pageSize)
     fillStart = stack_base;
     spillStart = fillStart + sizeof(MachInst) * numFillInsts;
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //Set up the thread context to start running the process
     //assert(NumArgumentRegs >= 2);
-    //threadContexts[0]->setIntReg(ArgumentReg[0], argc);
-    //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
-    threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
+    //tc->setIntReg(ArgumentReg[0], argc);
+    //tc->setIntReg(ArgumentReg[1], argv_array_base);
+    tc->setIntReg(StackPointerReg, stack_min - StackBias);
 
     // %g1 is a pointer to a function that should be run at exit. Since we
     // don't have anything like that, it should be set to 0.
-    threadContexts[0]->setIntReg(1, 0);
+    tc->setIntReg(1, 0);
 
     Addr prog_entry = objFile->entryPoint();
-    threadContexts[0]->setPC(prog_entry);
-    threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
-    threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+    tc->setPC(prog_entry);
+    tc->setNextPC(prog_entry + sizeof(MachInst));
+    tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
 
     //Align the "stack_min" to a page boundary.
     stack_min = roundDown(stack_min, pageSize);
@@ -505,3 +506,63 @@ void Sparc64LiveProcess::flushWindows(ThreadContext *tc)
     tc->setIntReg(NumIntArchRegs + 4, Canrestore);
     tc->setMiscReg(MISCREG_CWP, origCWP);
 }
+
+IntReg
+Sparc32LiveProcess::getSyscallArg(ThreadContext *tc, int &i)
+{
+    assert(i < 6);
+    return bits(tc->readIntReg(FirstArgumentReg + i++), 31, 0);
+}
+
+void
+Sparc32LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val)
+{
+    assert(i < 6);
+    tc->setIntReg(FirstArgumentReg + i, bits(val, 31, 0));
+}
+
+IntReg
+Sparc64LiveProcess::getSyscallArg(ThreadContext *tc, int &i)
+{
+    assert(i < 6);
+    return tc->readIntReg(FirstArgumentReg + i++);
+}
+
+void
+Sparc64LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val)
+{
+    assert(i < 6);
+    tc->setIntReg(FirstArgumentReg + i, val);
+}
+
+void
+SparcLiveProcess::setSyscallReturn(ThreadContext *tc,
+        SyscallReturn return_value)
+{
+    // 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
+        tc->setIntReg(NumIntArchRegs + 2,
+                tc->readIntReg(NumIntArchRegs + 2) & 0xEE);
+        //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE);
+        IntReg val = return_value.value();
+        if (bits(tc->readMiscRegNoEffect(
+                        SparcISA::MISCREG_PSTATE), 3, 3)) {
+            val = bits(val, 31, 0);
+        }
+        tc->setIntReg(ReturnValueReg, val);
+    } else {
+        // got an error, set XCC.C
+        tc->setIntReg(NumIntArchRegs + 2,
+                tc->readIntReg(NumIntArchRegs + 2) | 0x11);
+        //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11);
+        IntReg val = -return_value.value();
+        if (bits(tc->readMiscRegNoEffect(
+                        SparcISA::MISCREG_PSTATE), 3, 3)) {
+            val = bits(val, 31, 0);
+        }
+        tc->setIntReg(ReturnValueReg, val);
+    }
+}