diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 0d865e520..80ec360b7 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -40,7 +40,7 @@ namespace AlphaISA { uint64_t -getArgument(ThreadContext *tc, int number, bool fp) +getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) { #if FULL_SYSTEM const int NumArgumentRegs = 6; @@ -96,5 +96,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *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 diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 281fc4492..360e155f8 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -41,7 +41,7 @@ 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 inUserMode(ThreadContext *tc) @@ -94,6 +94,7 @@ void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); +void skipFunction(ThreadContext *tc); } // namespace AlphaISA #endif // __ARCH_ALPHA_UTILITY_HH__ 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(sp + + (number-NumArgumentRegs) * sizeof(uint32_t)); + // since two 32 bit args == 1 64 bit arg, increment number + number++; + } else { + arg = vp->read(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); + }; diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index ab6a00af3..7dd74551e 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -52,7 +52,7 @@ using namespace std; namespace MipsISA { uint64_t -getArgument(ThreadContext *tc, int number, bool fp) +getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) { #if FULL_SYSTEM if (number < 4) { @@ -264,5 +264,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) { 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 diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index f827e9b33..d073f3116 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -45,7 +45,7 @@ class ThreadContext; 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 copyMiscRegs(ThreadContext *src, ThreadContext *dest); +void skipFunction(ThreadContext *tc); + }; diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc index c3d49ed16..ece17f4d1 100644 --- a/src/arch/power/utility.cc +++ b/src/arch/power/utility.cc @@ -55,4 +55,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest) dest->setNextPC(src->readNextPC()); } +void +skipFunction(ThreadContext *tc) +{ + panic("Not Implemented for POWER"); +} + + } // PowerISA namespace diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh index b3eed9de3..c8cd441ba 100644 --- a/src/arch/power/utility.hh +++ b/src/arch/power/utility.hh @@ -61,6 +61,8 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) { } +void skipFunction(ThreadContext *tc); + } // PowerISA namespace #endif // __ARCH_POWER_UTILITY_HH__ diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index 9a062e841..e14be48e2 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -45,7 +45,7 @@ namespace SparcISA { //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 //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 const int NumArgumentRegs = 6; if (number < NumArgumentRegs) { @@ -218,6 +218,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest) 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 initCPU(ThreadContext *tc, int cpuId) { diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 70044a6c2..39e23aa26 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -41,7 +41,7 @@ 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 inUserMode(ThreadContext *tc) @@ -75,6 +75,8 @@ namespace SparcISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest); + void skipFunction(ThreadContext *tc); + } // namespace SparcISA #endif diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 50574bcde..d74bb74b6 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -52,7 +52,7 @@ 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 panic("getArgument() not implemented for x86!\n"); #else @@ -233,4 +233,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest) dest->setNextPC(src->readNextPC()); } +void +skipFunction(ThreadContext *tc) +{ + panic("Not implemented for x86\n"); +} + + } //namespace X86_ISA diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index bfa102529..fd9ac59fd 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -52,7 +52,7 @@ class ThreadContext; 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 inUserMode(ThreadContext *tc) @@ -83,6 +83,8 @@ namespace X86ISA void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); + + void skipFunction(ThreadContext *tc); }; #endif // __ARCH_X86_UTILITY_HH__ diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc index bd01ed9ed..25856e466 100644 --- a/src/kern/system_events.cc +++ b/src/kern/system_events.cc @@ -30,6 +30,7 @@ */ #include "arch/isa_traits.hh" +#include "arch/utility.hh" #include "base/trace.hh" #include "config/the_isa.hh" #include "cpu/thread_context.hh" @@ -40,14 +41,9 @@ using namespace TheISA; void SkipFuncEvent::process(ThreadContext *tc) { - Addr newpc = tc->readIntReg(ReturnAddressReg); - DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description, - tc->readPC(), newpc); + tc->readPC(), tc->readIntReg(ReturnAddressReg)); - tc->setPC(newpc); - tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst)); -#if ISA_HAS_DELAY_SLOT - tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst)); -#endif + // Call ISA specific code to do the skipping + TheISA::skipFunction(tc); } diff --git a/src/sim/arguments.cc b/src/sim/arguments.cc index 339a57f90..511fc630d 100644 --- a/src/sim/arguments.cc +++ b/src/sim/arguments.cc @@ -50,8 +50,8 @@ Arguments::Data::alloc(size_t size) } 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); } diff --git a/src/sim/arguments.hh b/src/sim/arguments.hh index abc3da812..97b848e03 100644 --- a/src/sim/arguments.hh +++ b/src/sim/arguments.hh @@ -45,7 +45,7 @@ class Arguments protected: ThreadContext *tc; int number; - uint64_t getArg(bool fp = false); + uint64_t getArg(uint8_t size, bool fp = false); protected: class Data : public RefCounted @@ -82,7 +82,7 @@ class Arguments // for checking if an argument is NULL bool operator!() { - return getArg() == 0; + return getArg(TheISA::MachineBytes) == 0; } Arguments &operator++() { @@ -130,20 +130,20 @@ class Arguments template operator T() { assert(sizeof(T) <= sizeof(uint64_t)); - T data = static_cast(getArg()); + T data = static_cast(getArg(sizeof(T))); return data; } template operator T *() { T *buf = (T *)data->alloc(sizeof(T)); - CopyData(tc, buf, getArg(), sizeof(T)); + CopyData(tc, buf, getArg(sizeof(T)), sizeof(T)); return buf; } operator char *() { char *buf = data->alloc(2048); - CopyStringOut(tc, buf, getArg(), 2048); + CopyStringOut(tc, buf, getArg(TheISA::MachineBytes), 2048); return buf; } };