diff options
Diffstat (limited to 'src/arch/arm/utility.cc')
-rw-r--r-- | src/arch/arm/utility.cc | 60 |
1 files changed, 51 insertions, 9 deletions
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)); +} + } |