summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/system.hh5
-rw-r--r--src/arch/arm/utility.cc60
-rw-r--r--src/arch/arm/utility.hh4
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);
+
};