Debug: Implement getArgument() and function skipping for ARM.
authorAli Saidi <Ali.Saidi@ARM.com>
Fri, 1 Oct 2010 21:02:46 +0000 (16:02 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Fri, 1 Oct 2010 21:02:46 +0000 (16:02 -0500)
In the process make add skipFuction() to handle isa specific function skipping
instead of ifdefs and other ugliness. For almost all ABIs, 64 bit arguments can
only start in even registers.  Size is now passed to getArgument() so that 32
bit systems can make decisions about register selection for 64 bit arguments.
The number argument is now passed by reference because getArgument() will need
to change it based on the size of the argument and the current argument number.

For ARM, if the argument number is odd and a 64-bit register is requested the
number must first be incremented to because all 64 bit arguments are passed
in an even argument register. Then the number will be incremented again to
access both halves of the argument.

16 files changed:
src/arch/alpha/utility.cc
src/arch/alpha/utility.hh
src/arch/arm/system.hh
src/arch/arm/utility.cc
src/arch/arm/utility.hh
src/arch/mips/utility.cc
src/arch/mips/utility.hh
src/arch/power/utility.cc
src/arch/power/utility.hh
src/arch/sparc/utility.cc
src/arch/sparc/utility.hh
src/arch/x86/utility.cc
src/arch/x86/utility.hh
src/kern/system_events.cc
src/sim/arguments.cc
src/sim/arguments.hh

index 0d865e5208df9b17b44d984c0d36286f3fba2a77..80ec360b7b6404ad82b13aa337f49a2ec5899b0b 100644 (file)
@@ -40,7 +40,7 @@
 namespace AlphaISA {
 
 uint64_t
-getArgument(ThreadContext *tc, int number, bool fp)
+getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp)
 {
 #if FULL_SYSTEM
     const int NumArgumentRegs = 6;
@@ -96,5 +96,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
     copyIprs(src, dest);
 }
 
+void
+skipFunction(ThreadContext *tc)
+{
+    Addr newpc = tc->readIntReg(ReturnAddressReg);
+    tc->setPC(newpc);
+    tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+}
+
+
 } // namespace AlphaISA
 
index 281fc4492ff4b93f6e1f033311da149e54490b58..360e155f811f55199438121be54c0b23d5557b57 100644 (file)
@@ -41,7 +41,7 @@
 
 namespace AlphaISA {
 
-uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size,  bool fp);
 
 inline bool
 inUserMode(ThreadContext *tc)
@@ -94,6 +94,7 @@ void copyRegs(ThreadContext *src, ThreadContext *dest);
 
 void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
 
+void skipFunction(ThreadContext *tc);
 } // namespace AlphaISA
 
 #endif // __ARCH_ALPHA_UTILITY_HH__
index adf6d4f7b5352f72a818eddff545162e79042421..fe5ba64476670e888b58f09c51ca1b555a06ab17 100644 (file)
@@ -67,7 +67,10 @@ class ArmSystem : public System
     
     virtual Addr fixFuncEventAddr(Addr addr)
     {
-        //XXX This may eventually have to do something useful.
+        // Remove the low bit that thumb symbols have set
+        // but that aren't actually odd aligned
+        if (addr & 0x1)
+            return (addr & ~1) | PcTBit;
         return addr;
     }
 };
index 3e574ccafcf0f8088f4a9eeb83507c378ec80cf4..9672c5136a3ecb823c087e2200ccf47550d4b509 100644 (file)
 #include "arch/arm/utility.hh"
 #include "cpu/thread_context.hh"
 
+#if FULL_SYSTEM
+#include "arch/arm/vtophys.hh"
+#include "mem/vport.hh"
+#endif
 
 namespace ArmISA {
 
@@ -57,17 +61,43 @@ initCPU(ThreadContext *tc, int cpuId)
         reset->invoke(tc);
 }
 
-uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) {
 #if FULL_SYSTEM
+    if (fp)
+        panic("getArgument(): Floating point arguments not implemented\n");
+
     if (number < NumArgumentRegs) {
-        if (fp)
-            panic("getArgument(): Floating point arguments not implemented\n");
-        else
-            return tc->readIntReg(number);
-    }
-    else {
-        panic("getArgument(): Argument index %d beyond max supported (%d).\n",
-              number, NumArgumentRegs - 1);
+        // If the argument is 64 bits, it must be in an even regiser number
+        // Increment the number here if it isn't even
+        if (size == sizeof(uint64_t)) {
+            if ((number % 2) != 0)
+                number++;
+            // Read the two halves of the data
+            // number is inc here to get the second half of the 64 bit reg
+            uint64_t tmp;
+            tmp = tc->readIntReg(number++);
+            tmp |= tc->readIntReg(number) << 32;
+            return tmp;
+        } else {
+           return tc->readIntReg(number);
+        }
+    } else {
+        Addr sp = tc->readIntReg(StackPointerReg);
+        VirtualPort *vp = tc->getVirtPort();
+        uint64_t arg;
+        if (size == sizeof(uint64_t)) {
+            // If the argument is even it must be aligned
+            if ((number % 2) != 0)
+                number++;
+            arg = vp->read<uint64_t>(sp +
+                    (number-NumArgumentRegs) * sizeof(uint32_t));
+            // since two 32 bit args == 1 64 bit arg, increment number
+            number++;
+        } else {
+            arg = vp->read<uint32_t>(sp +
+                           (number-NumArgumentRegs) * sizeof(uint32_t));
+        }
+        return arg;
     }
 #else
     panic("getArgument() only implemented for FULL_SYSTEM\n");
@@ -90,5 +120,17 @@ readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2)
 
 }
 
+void
+skipFunction(ThreadContext *tc)
+{
+    Addr newpc = tc->readIntReg(ReturnAddressReg);
+    newpc &= ~ULL(1);
+    if (isThumb(tc->readPC()))
+        tc->setPC(newpc | PcTBit);
+    else
+        tc->setPC(newpc);
+    tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+}
+
 
 }
index 8c2ccd4f66115bcc033e243f5c4de9ed82d07a38..21c0a9c0494fe1bf5026547fb29984b5a61e0eb2 100644 (file)
@@ -156,11 +156,13 @@ namespace ArmISA {
         return !cpacr.asedis && vfpEnabled(cpacr, cpsr, fpexc);
     }
 
-uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
     
 Fault setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
 Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
 
+void skipFunction(ThreadContext *tc);
+
 };
 
 
index ab6a00af379a9173677497db5d3b1af6858963ad..7dd74551ea6a64355f374b082b5ad1b7b318e261 100644 (file)
@@ -52,7 +52,7 @@ using namespace std;
 namespace MipsISA {
 
 uint64_t
-getArgument(ThreadContext *tc, int number, bool fp)
+getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp)
 {
 #if FULL_SYSTEM
     if (number < 4) {
@@ -264,5 +264,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
 {
     panic("Copy Misc. Regs Not Implemented Yet\n");
 }
+void
+skipFunction(ThreadContext *tc)
+{
+    Addr newpc = tc->readIntReg(ReturnAddressReg);
+    tc->setPC(newpc);
+    tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+    tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+}
+
 
 } // namespace MipsISA
index f827e9b33a80f7e3aff9867ed6ea5ad4c33ff7a1..d073f311680f4f3e9553fe2620ab0d8065d6329c 100644 (file)
@@ -45,7 +45,7 @@ class ThreadContext;
 
 namespace MipsISA {
 
-uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
 
 ////////////////////////////////////////////////////////////////////////
 //
@@ -103,6 +103,8 @@ void startupCPU(ThreadContext *tc, int cpuId);
 void copyRegs(ThreadContext *src, ThreadContext *dest);
 void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
 
+void skipFunction(ThreadContext *tc);
+
 };
 
 
index c3d49ed169c9a63c7ae5bd5cee36513153a39eb9..ece17f4d174b335be0bbcff5ec405d5826b41d44 100644 (file)
@@ -55,4 +55,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
     dest->setNextPC(src->readNextPC());
 }
 
+void
+skipFunction(ThreadContext *tc)
+{
+    panic("Not Implemented for POWER");
+}
+
+
 } // PowerISA namespace
index b3eed9de34d6023cedcafbf3f553cf7ee4b9f3ec..c8cd441ba33a98eafc0b388a7a1c0b7b8f3faddb 100644 (file)
@@ -61,6 +61,8 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
 {
 }
 
+void skipFunction(ThreadContext *tc);
+
 } // PowerISA namespace
 
 #endif // __ARCH_POWER_UTILITY_HH__
index 9a062e841ac664d32d2efd3f8db6cf34fe469049..e14be48e2d7ba5e3d6b3addd6a4bbf868d1ce8bf 100644 (file)
@@ -45,7 +45,7 @@ namespace SparcISA {
 //the sixth are passed on the stack past the 16 word window save area,
 //space for the struct/union return pointer, and space reserved for the
 //first 6 arguments which the caller may use but doesn't have to.
-uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) {
 #if FULL_SYSTEM
     const int NumArgumentRegs = 6;
     if (number < NumArgumentRegs) {
@@ -218,6 +218,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
     dest->setNextNPC(src->readNextNPC());
 }
 
+void
+skipFunction(ThreadContext *tc)
+{
+    Addr newpc = tc->readIntReg(ReturnAddressReg);
+    tc->setPC(newpc);
+    tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+    tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+}
+
+
 void
 initCPU(ThreadContext *tc, int cpuId)
 {
index 70044a6c2a1332fc3ad9ad7c1f5afae4b73736a3..39e23aa26b5120e24b28c40b55495dc2b7bf5cc4 100644 (file)
@@ -41,7 +41,7 @@
 
 namespace SparcISA
 {
-    uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+    uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
 
     static inline bool
     inUserMode(ThreadContext *tc)
@@ -75,6 +75,8 @@ namespace SparcISA
 
     void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
 
+    void skipFunction(ThreadContext *tc);
+
 } // namespace SparcISA
 
 #endif
index 50574bcde487916c6d93dd7041467ff5cbe7f7e6..d74bb74b6ca4816b4f3b3d251b3cbbdec2f8db05 100644 (file)
@@ -52,7 +52,7 @@
 
 namespace X86ISA {
 
-uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) {
 #if FULL_SYSTEM
     panic("getArgument() not implemented for x86!\n");
 #else
@@ -233,4 +233,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
     dest->setNextPC(src->readNextPC());
 }
 
+void
+skipFunction(ThreadContext *tc)
+{
+    panic("Not implemented for x86\n");
+}
+
+
 } //namespace X86_ISA
index bfa1025296f4a99f18447c078c0b090b8711ed94..fd9ac59fde2c303e7338f1fe83c1bad79a08c429 100644 (file)
@@ -52,7 +52,7 @@ class ThreadContext;
 
 namespace X86ISA
 {
-    uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+    uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
 
     static inline bool
     inUserMode(ThreadContext *tc)
@@ -83,6 +83,8 @@ namespace X86ISA
     void copyRegs(ThreadContext *src, ThreadContext *dest);
 
     void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
+
+    void skipFunction(ThreadContext *tc);
 };
 
 #endif // __ARCH_X86_UTILITY_HH__
index bd01ed9ede0a1834cd1fd6fb00a6115f4e4e5027..25856e4662d65ce9530b55e50a860ba0e62c6727 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "arch/isa_traits.hh"
+#include "arch/utility.hh"
 #include "base/trace.hh"
 #include "config/the_isa.hh"
 #include "cpu/thread_context.hh"
@@ -40,14 +41,9 @@ using namespace TheISA;
 void
 SkipFuncEvent::process(ThreadContext *tc)
 {
-    Addr newpc = tc->readIntReg(ReturnAddressReg);
-
     DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
-            tc->readPC(), newpc);
+            tc->readPC(), tc->readIntReg(ReturnAddressReg));
 
-    tc->setPC(newpc);
-    tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
-#if ISA_HAS_DELAY_SLOT
-    tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
-#endif
+    // Call ISA specific code to do the skipping
+    TheISA::skipFunction(tc);
 }
index 339a57f909895cf4973c99e03fa3137e1ee50fae..511fc630d36862346a8ab12188d5461d69f3cdb4 100644 (file)
@@ -50,8 +50,8 @@ Arguments::Data::alloc(size_t size)
 }
 
 uint64_t
-Arguments::getArg(bool fp)
+Arguments::getArg(uint8_t size, bool fp)
 {
-    return TheISA::getArgument(tc, number, fp);
+    return TheISA::getArgument(tc, number, size, fp);
 }
 
index abc3da812a93b499e17d4c4279e5eaac7086a783..97b848e03046c26db82f9b1cf3f971e37dbbe9a7 100644 (file)
@@ -45,7 +45,7 @@ class Arguments
   protected:
     ThreadContext *tc;
     int number;
-    uint64_t getArg(bool fp = false);
+    uint64_t getArg(uint8_t size, bool fp = false);
 
   protected:
     class Data : public RefCounted
@@ -82,7 +82,7 @@ class Arguments
 
     // for checking if an argument is NULL
     bool operator!() {
-        return getArg() == 0;
+        return getArg(TheISA::MachineBytes) == 0;
     }
 
     Arguments &operator++() {
@@ -130,20 +130,20 @@ class Arguments
     template <class T>
     operator T() {
         assert(sizeof(T) <= sizeof(uint64_t));
-        T data = static_cast<T>(getArg());
+        T data = static_cast<T>(getArg(sizeof(T)));
         return data;
     }
 
     template <class T>
     operator T *() {
         T *buf = (T *)data->alloc(sizeof(T));
-        CopyData(tc, buf, getArg(), sizeof(T));
+        CopyData(tc, buf, getArg(sizeof(T)), sizeof(T));
         return buf;
     }
 
     operator char *() {
         char *buf = data->alloc(2048);
-        CopyStringOut(tc, buf, getArg(), 2048);
+        CopyStringOut(tc, buf, getArg(TheISA::MachineBytes), 2048);
         return buf;
     }
 };