summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2010-10-01 16:02:46 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2010-10-01 16:02:46 -0500
commit518b5e5b1c71259ce0badc29f98db46a73c59442 (patch)
tree40260de5559f292aac501ca99f2b1f0b72098cb8
parentb331b02669f95adf4744b1e7db50ad4b231fb704 (diff)
downloadgem5-518b5e5b1c71259ce0badc29f98db46a73c59442.tar.xz
Debug: Implement getArgument() and function skipping for ARM.
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.
-rw-r--r--src/arch/alpha/utility.cc11
-rw-r--r--src/arch/alpha/utility.hh3
-rw-r--r--src/arch/arm/system.hh5
-rw-r--r--src/arch/arm/utility.cc60
-rw-r--r--src/arch/arm/utility.hh4
-rw-r--r--src/arch/mips/utility.cc11
-rw-r--r--src/arch/mips/utility.hh4
-rw-r--r--src/arch/power/utility.cc7
-rw-r--r--src/arch/power/utility.hh2
-rw-r--r--src/arch/sparc/utility.cc12
-rw-r--r--src/arch/sparc/utility.hh4
-rw-r--r--src/arch/x86/utility.cc9
-rw-r--r--src/arch/x86/utility.hh4
-rw-r--r--src/kern/system_events.cc12
-rw-r--r--src/sim/arguments.cc4
-rw-r--r--src/sim/arguments.hh10
16 files changed, 128 insertions, 34 deletions
diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc
index 0d865e520..80ec360b7 100644
--- a/src/arch/alpha/utility.cc
+++ b/src/arch/alpha/utility.cc
@@ -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
diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
index 281fc4492..360e155f8 100644
--- a/src/arch/alpha/utility.hh
+++ b/src/arch/alpha/utility.hh
@@ -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__
diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh
index adf6d4f7b..fe5ba6447 100644
--- a/src/arch/arm/system.hh
+++ b/src/arch/arm/system.hh
@@ -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;
}
};
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index 3e574ccaf..9672c5136 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -42,6 +42,10 @@
#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));
+}
+
}
diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh
index 8c2ccd4f6..21c0a9c04 100644
--- a/src/arch/arm/utility.hh
+++ b/src/arch/arm/utility.hh
@@ -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);
+
};
diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc
index ab6a00af3..7dd74551e 100644
--- a/src/arch/mips/utility.cc
+++ b/src/arch/mips/utility.cc
@@ -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
diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh
index f827e9b33..d073f3116 100644
--- a/src/arch/mips/utility.hh
+++ b/src/arch/mips/utility.hh
@@ -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);
+
};
diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc
index c3d49ed16..ece17f4d1 100644
--- a/src/arch/power/utility.cc
+++ b/src/arch/power/utility.cc
@@ -55,4 +55,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
dest->setNextPC(src->readNextPC());
}
+void
+skipFunction(ThreadContext *tc)
+{
+ panic("Not Implemented for POWER");
+}
+
+
} // PowerISA namespace
diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh
index b3eed9de3..c8cd441ba 100644
--- a/src/arch/power/utility.hh
+++ b/src/arch/power/utility.hh
@@ -61,6 +61,8 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
}
+void skipFunction(ThreadContext *tc);
+
} // PowerISA namespace
#endif // __ARCH_POWER_UTILITY_HH__
diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc
index 9a062e841..e14be48e2 100644
--- a/src/arch/sparc/utility.cc
+++ b/src/arch/sparc/utility.cc
@@ -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) {
@@ -219,6 +219,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
}
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)
{
static Fault por = new PowerOnReset();
diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh
index 70044a6c2..39e23aa26 100644
--- a/src/arch/sparc/utility.hh
+++ b/src/arch/sparc/utility.hh
@@ -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
diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc
index 50574bcde..d74bb74b6 100644
--- a/src/arch/x86/utility.cc
+++ b/src/arch/x86/utility.cc
@@ -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
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index bfa102529..fd9ac59fd 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -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__
diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc
index bd01ed9ed..25856e466 100644
--- a/src/kern/system_events.cc
+++ b/src/kern/system_events.cc
@@ -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);
}
diff --git a/src/sim/arguments.cc b/src/sim/arguments.cc
index 339a57f90..511fc630d 100644
--- a/src/sim/arguments.cc
+++ b/src/sim/arguments.cc
@@ -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);
}
diff --git a/src/sim/arguments.hh b/src/sim/arguments.hh
index abc3da812..97b848e03 100644
--- a/src/sim/arguments.hh
+++ b/src/sim/arguments.hh
@@ -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;
}
};