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.
This commit is contained in:
parent
b331b02669
commit
518b5e5b1c
16 changed files with 128 additions and 34 deletions
|
@ -40,7 +40,7 @@
|
||||||
namespace AlphaISA {
|
namespace AlphaISA {
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
getArgument(ThreadContext *tc, int number, bool fp)
|
getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
const int NumArgumentRegs = 6;
|
const int NumArgumentRegs = 6;
|
||||||
|
@ -96,5 +96,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
copyIprs(src, 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
|
} // namespace AlphaISA
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
namespace AlphaISA {
|
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
|
inline bool
|
||||||
inUserMode(ThreadContext *tc)
|
inUserMode(ThreadContext *tc)
|
||||||
|
@ -94,6 +94,7 @@ void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
|
void skipFunction(ThreadContext *tc);
|
||||||
} // namespace AlphaISA
|
} // namespace AlphaISA
|
||||||
|
|
||||||
#endif // __ARCH_ALPHA_UTILITY_HH__
|
#endif // __ARCH_ALPHA_UTILITY_HH__
|
||||||
|
|
|
@ -67,7 +67,10 @@ class ArmSystem : public System
|
||||||
|
|
||||||
virtual Addr fixFuncEventAddr(Addr addr)
|
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;
|
return addr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
#include "arch/arm/utility.hh"
|
#include "arch/arm/utility.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
#include "arch/arm/vtophys.hh"
|
||||||
|
#include "mem/vport.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ArmISA {
|
namespace ArmISA {
|
||||||
|
|
||||||
|
@ -57,17 +61,43 @@ initCPU(ThreadContext *tc, int cpuId)
|
||||||
reset->invoke(tc);
|
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 FULL_SYSTEM
|
||||||
if (number < NumArgumentRegs) {
|
|
||||||
if (fp)
|
if (fp)
|
||||||
panic("getArgument(): Floating point arguments not implemented\n");
|
panic("getArgument(): Floating point arguments not implemented\n");
|
||||||
else
|
|
||||||
|
if (number < NumArgumentRegs) {
|
||||||
|
// 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);
|
return tc->readIntReg(number);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
panic("getArgument(): Argument index %d beyond max supported (%d).\n",
|
Addr sp = tc->readIntReg(StackPointerReg);
|
||||||
number, NumArgumentRegs - 1);
|
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
|
#else
|
||||||
panic("getArgument() only implemented for FULL_SYSTEM\n");
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,11 +156,13 @@ namespace ArmISA {
|
||||||
return !cpacr.asedis && vfpEnabled(cpacr, cpsr, fpexc);
|
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 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);
|
Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
|
||||||
|
|
||||||
|
void skipFunction(ThreadContext *tc);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ using namespace std;
|
||||||
namespace MipsISA {
|
namespace MipsISA {
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
getArgument(ThreadContext *tc, int number, bool fp)
|
getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
if (number < 4) {
|
if (number < 4) {
|
||||||
|
@ -264,5 +264,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
{
|
{
|
||||||
panic("Copy Misc. Regs Not Implemented Yet\n");
|
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
|
} // namespace MipsISA
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace MipsISA {
|
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 copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
|
void skipFunction(ThreadContext *tc);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,4 +55,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
dest->setNextPC(src->readNextPC());
|
dest->setNextPC(src->readNextPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
skipFunction(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
panic("Not Implemented for POWER");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // PowerISA namespace
|
} // PowerISA namespace
|
||||||
|
|
|
@ -61,6 +61,8 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void skipFunction(ThreadContext *tc);
|
||||||
|
|
||||||
} // PowerISA namespace
|
} // PowerISA namespace
|
||||||
|
|
||||||
#endif // __ARCH_POWER_UTILITY_HH__
|
#endif // __ARCH_POWER_UTILITY_HH__
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace SparcISA {
|
||||||
//the sixth are passed on the stack past the 16 word window save area,
|
//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
|
//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.
|
//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
|
#if FULL_SYSTEM
|
||||||
const int NumArgumentRegs = 6;
|
const int NumArgumentRegs = 6;
|
||||||
if (number < NumArgumentRegs) {
|
if (number < NumArgumentRegs) {
|
||||||
|
@ -218,6 +218,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
dest->setNextNPC(src->readNextNPC());
|
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
|
void
|
||||||
initCPU(ThreadContext *tc, int cpuId)
|
initCPU(ThreadContext *tc, int cpuId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
namespace SparcISA
|
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
|
static inline bool
|
||||||
inUserMode(ThreadContext *tc)
|
inUserMode(ThreadContext *tc)
|
||||||
|
@ -75,6 +75,8 @@ namespace SparcISA
|
||||||
|
|
||||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
|
void skipFunction(ThreadContext *tc);
|
||||||
|
|
||||||
} // namespace SparcISA
|
} // namespace SparcISA
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
namespace X86ISA {
|
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
|
#if FULL_SYSTEM
|
||||||
panic("getArgument() not implemented for x86!\n");
|
panic("getArgument() not implemented for x86!\n");
|
||||||
#else
|
#else
|
||||||
|
@ -233,4 +233,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
dest->setNextPC(src->readNextPC());
|
dest->setNextPC(src->readNextPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
skipFunction(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
panic("Not implemented for x86\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} //namespace X86_ISA
|
} //namespace X86_ISA
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace X86ISA
|
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
|
static inline bool
|
||||||
inUserMode(ThreadContext *tc)
|
inUserMode(ThreadContext *tc)
|
||||||
|
@ -83,6 +83,8 @@ namespace X86ISA
|
||||||
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
|
void skipFunction(ThreadContext *tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ARCH_X86_UTILITY_HH__
|
#endif // __ARCH_X86_UTILITY_HH__
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
|
#include "arch/utility.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
@ -40,14 +41,9 @@ using namespace TheISA;
|
||||||
void
|
void
|
||||||
SkipFuncEvent::process(ThreadContext *tc)
|
SkipFuncEvent::process(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
Addr newpc = tc->readIntReg(ReturnAddressReg);
|
|
||||||
|
|
||||||
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
|
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
|
||||||
tc->readPC(), newpc);
|
tc->readPC(), tc->readIntReg(ReturnAddressReg));
|
||||||
|
|
||||||
tc->setPC(newpc);
|
// Call ISA specific code to do the skipping
|
||||||
tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
|
TheISA::skipFunction(tc);
|
||||||
#if ISA_HAS_DELAY_SLOT
|
|
||||||
tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@ Arguments::Data::alloc(size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Arguments
|
||||||
protected:
|
protected:
|
||||||
ThreadContext *tc;
|
ThreadContext *tc;
|
||||||
int number;
|
int number;
|
||||||
uint64_t getArg(bool fp = false);
|
uint64_t getArg(uint8_t size, bool fp = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class Data : public RefCounted
|
class Data : public RefCounted
|
||||||
|
@ -82,7 +82,7 @@ class Arguments
|
||||||
|
|
||||||
// for checking if an argument is NULL
|
// for checking if an argument is NULL
|
||||||
bool operator!() {
|
bool operator!() {
|
||||||
return getArg() == 0;
|
return getArg(TheISA::MachineBytes) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arguments &operator++() {
|
Arguments &operator++() {
|
||||||
|
@ -130,20 +130,20 @@ class Arguments
|
||||||
template <class T>
|
template <class T>
|
||||||
operator T() {
|
operator T() {
|
||||||
assert(sizeof(T) <= sizeof(uint64_t));
|
assert(sizeof(T) <= sizeof(uint64_t));
|
||||||
T data = static_cast<T>(getArg());
|
T data = static_cast<T>(getArg(sizeof(T)));
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
operator T *() {
|
operator T *() {
|
||||||
T *buf = (T *)data->alloc(sizeof(T));
|
T *buf = (T *)data->alloc(sizeof(T));
|
||||||
CopyData(tc, buf, getArg(), sizeof(T));
|
CopyData(tc, buf, getArg(sizeof(T)), sizeof(T));
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator char *() {
|
operator char *() {
|
||||||
char *buf = data->alloc(2048);
|
char *buf = data->alloc(2048);
|
||||||
CopyStringOut(tc, buf, getArg(), 2048);
|
CopyStringOut(tc, buf, getArg(TheISA::MachineBytes), 2048);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue