diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2010-10-01 16:02:46 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2010-10-01 16:02:46 -0500 |
commit | 518b5e5b1c71259ce0badc29f98db46a73c59442 (patch) | |
tree | 40260de5559f292aac501ca99f2b1f0b72098cb8 /src/arch/arm | |
parent | b331b02669f95adf4744b1e7db50ad4b231fb704 (diff) | |
download | gem5-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.
Diffstat (limited to 'src/arch/arm')
-rw-r--r-- | src/arch/arm/system.hh | 5 | ||||
-rw-r--r-- | src/arch/arm/utility.cc | 60 | ||||
-rw-r--r-- | src/arch/arm/utility.hh | 4 |
3 files changed, 58 insertions, 11 deletions
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); + }; |