diff options
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); + }; |