diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/kvm/arm_cpu.cc | 5 | ||||
-rw-r--r-- | src/arch/generic/mmapped_ipr.cc | 2 | ||||
-rw-r--r-- | src/sim/pseudo_inst.cc | 144 | ||||
-rw-r--r-- | src/sim/pseudo_inst.hh | 188 |
4 files changed, 179 insertions, 160 deletions
diff --git a/src/arch/arm/kvm/arm_cpu.cc b/src/arch/arm/kvm/arm_cpu.cc index 4d6b9a1b3..0a77ee0d6 100644 --- a/src/arch/arm/kvm/arm_cpu.cc +++ b/src/arch/arm/kvm/arm_cpu.cc @@ -320,8 +320,9 @@ ArmKvmCPU::onKvmExitHypercall() const uint8_t func((reg_ip >> 8) & 0xFF); const uint8_t subfunc(reg_ip & 0xFF); - DPRINTF(Kvm, "KVM Hypercall: 0x%x/0x%x\n", func, subfunc); - const uint64_t ret(PseudoInst::pseudoInst(getContext(0), func, subfunc)); + DPRINTF(Kvm, "KVM Hypercall: %#x/%#x\n", func, subfunc); + const uint64_t ret = + PseudoInst::pseudoInst<PseudoInstABI>(getContext(0), func, subfunc); // Just set the return value using the KVM API instead of messing // with the context. We could have used the context, but that diff --git a/src/arch/generic/mmapped_ipr.cc b/src/arch/generic/mmapped_ipr.cc index bf6bf99f4..8bdd18016 100644 --- a/src/arch/generic/mmapped_ipr.cc +++ b/src/arch/generic/mmapped_ipr.cc @@ -47,7 +47,7 @@ handlePseudoInst(ThreadContext *xc, Packet *pkt) uint64_t ret; assert((offset >> 16) == 0); - ret = PseudoInst::pseudoInst(xc, func, subfunc); + ret = PseudoInst::pseudoInst<PseudoInstABI>(xc, func, subfunc); if (pkt->isRead()) pkt->set(ret, TheISA::GuestByteOrder); } diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 53892b5d1..bd2c64e04 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -51,10 +51,6 @@ #include <string> #include <vector> -#include <gem5/asm/generic/m5ops.h> - -#include "arch/pseudo_inst.hh" -#include "arch/utility.hh" #include "arch/vtophys.hh" #include "base/debug.hh" #include "base/output.hh" @@ -63,7 +59,6 @@ #include "cpu/quiesce_event.hh" #include "cpu/thread_context.hh" #include "debug/Loader.hh" -#include "debug/PseudoInst.hh" #include "debug/Quiesce.hh" #include "debug/WorkItems.hh" #include "dev/net/dist_iface.hh" @@ -81,11 +76,10 @@ #include "sim/vptr.hh" using namespace std; - using namespace Stats; -using namespace TheISA; -namespace PseudoInst { +namespace PseudoInst +{ static inline void panicFsOnlyPseudoInst(const char *name) @@ -93,140 +87,6 @@ panicFsOnlyPseudoInst(const char *name) panic("Pseudo inst \"%s\" is only available in Full System mode."); } -uint64_t -pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc) -{ - uint64_t args[4]; - - DPRINTF(PseudoInst, "PseudoInst::pseudoInst(%i, %i)\n", func, subfunc); - - // We need to do this in a slightly convoluted way since - // getArgument() might have side-effects on arg_num. We could have - // used the Argument class, but due to the possible side effects - // from getArgument, it'd most likely break. - int arg_num(0); - for (int i = 0; i < sizeof(args) / sizeof(*args); ++i) { - args[arg_num] = getArgument(tc, arg_num, sizeof(uint64_t), false); - ++arg_num; - } - - switch (func) { - case M5OP_ARM: - arm(tc); - break; - - case M5OP_QUIESCE: - quiesce(tc); - break; - - case M5OP_QUIESCE_NS: - quiesceNs(tc, args[0]); - break; - - case M5OP_QUIESCE_CYCLE: - quiesceCycles(tc, args[0]); - break; - - case M5OP_QUIESCE_TIME: - return quiesceTime(tc); - - case M5OP_RPNS: - return rpns(tc); - - case M5OP_WAKE_CPU: - wakeCPU(tc, args[0]); - break; - - case M5OP_EXIT: - m5exit(tc, args[0]); - break; - - case M5OP_FAIL: - m5fail(tc, args[0], args[1]); - break; - - case M5OP_INIT_PARAM: - return initParam(tc, args[0], args[1]); - - case M5OP_LOAD_SYMBOL: - loadsymbol(tc); - break; - - case M5OP_RESET_STATS: - resetstats(tc, args[0], args[1]); - break; - - case M5OP_DUMP_STATS: - dumpstats(tc, args[0], args[1]); - break; - - case M5OP_DUMP_RESET_STATS: - dumpresetstats(tc, args[0], args[1]); - break; - - case M5OP_CHECKPOINT: - m5checkpoint(tc, args[0], args[1]); - break; - - case M5OP_WRITE_FILE: - return writefile(tc, args[0], args[1], args[2], args[3]); - - case M5OP_READ_FILE: - return readfile(tc, args[0], args[1], args[2]); - - case M5OP_DEBUG_BREAK: - debugbreak(tc); - break; - - case M5OP_SWITCH_CPU: - switchcpu(tc); - break; - - case M5OP_ADD_SYMBOL: - addsymbol(tc, args[0], args[1]); - break; - - case M5OP_PANIC: - panic("M5 panic instruction called at %s\n", tc->pcState()); - - case M5OP_WORK_BEGIN: - workbegin(tc, args[0], args[1]); - break; - - case M5OP_WORK_END: - workend(tc, args[0], args[1]); - break; - - case M5OP_ANNOTATE: - case M5OP_RESERVED2: - case M5OP_RESERVED3: - case M5OP_RESERVED4: - case M5OP_RESERVED5: - warn("Unimplemented m5 op (0x%x)\n", func); - break; - - /* SE mode functions */ - case M5OP_SE_SYSCALL: - m5Syscall(tc); - break; - - case M5OP_SE_PAGE_FAULT: - m5PageFault(tc); - break; - - /* dist-gem5 functions */ - case M5OP_DIST_TOGGLE_SYNC: - togglesync(tc); - break; - - default: - warn("Unhandled m5 op: 0x%x\n", func); - break; - } - - return 0; -} - void arm(ThreadContext *tc) { diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 977ed1d39..8685b8257 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -43,25 +43,48 @@ #ifndef __SIM_PSEUDO_INST_HH__ #define __SIM_PSEUDO_INST_HH__ +#include <gem5/asm/generic/m5ops.h> + class ThreadContext; -//We need the "Tick" and "Addr" data types from here -#include "base/types.hh" +#include "arch/pseudo_inst.hh" +#include "arch/utility.hh" +#include "base/types.hh" // For Tick and Addr data types. +#include "debug/PseudoInst.hh" +#include "sim/guest_abi.hh" -namespace PseudoInst { +struct PseudoInstABI +{ + using Position = int; +}; -/** - * Execute a decoded M5 pseudo instruction - * - * The ISA-specific code is responsible to decode the pseudo inst - * function number and subfunction number. After that has been done, - * the rest of the instruction can be implemented in an ISA-agnostic - * manner using the ISA-specific getArguments functions. - * - * @param func M5 pseudo op major function number (see utility/m5/m5ops.h) - * @param subfunc M5 minor function number. Mainly used for annotations. - */ -uint64_t pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc); +namespace GuestABI +{ + +template <typename T> +struct Result<PseudoInstABI, T> +{ + static void + store(ThreadContext *tc, const T &ret) + { + // Don't do anything with the pseudo inst results by default. + } +}; + +template <> +struct Argument<PseudoInstABI, uint64_t> +{ + static uint64_t + get(ThreadContext *tc, PseudoInstABI::Position &position) + { + return TheISA::getArgument(tc, position, sizeof(uint64_t), false); + } +}; + +} // namespace GuestABI + +namespace PseudoInst +{ void arm(ThreadContext *tc); void quiesce(ThreadContext *tc); @@ -91,6 +114,141 @@ void workend(ThreadContext *tc, uint64_t workid, uint64_t threadid); void m5Syscall(ThreadContext *tc); void togglesync(ThreadContext *tc); +/** + * Execute a decoded M5 pseudo instruction + * + * The ISA-specific code is responsible to decode the pseudo inst + * function number and subfunction number. After that has been done, + * the rest of the instruction can be implemented in an ISA-agnostic + * manner using the ISA-specific getArguments functions. + * + * @param func M5 pseudo op major function number (see utility/m5/m5ops.h) + * @param subfunc M5 minor function number. Mainly used for annotations. + */ + +template <typename ABI> +uint64_t +pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc) +{ + DPRINTF(PseudoInst, "PseudoInst::pseudoInst(%i, %i)\n", func, subfunc); + + switch (func) { + case M5OP_ARM: + invokeSimcall<ABI>(tc, arm); + break; + + case M5OP_QUIESCE: + invokeSimcall<ABI>(tc, quiesce); + break; + + case M5OP_QUIESCE_NS: + invokeSimcall<ABI>(tc, quiesceNs); + break; + + case M5OP_QUIESCE_CYCLE: + invokeSimcall<ABI>(tc, quiesceCycles); + break; + + case M5OP_QUIESCE_TIME: + return invokeSimcall<ABI>(tc, quiesceTime); + + case M5OP_RPNS: + return invokeSimcall<ABI>(tc, rpns); + + case M5OP_WAKE_CPU: + invokeSimcall<ABI>(tc, wakeCPU); + break; + + case M5OP_EXIT: + invokeSimcall<ABI>(tc, m5exit); + break; + + case M5OP_FAIL: + invokeSimcall<ABI>(tc, m5fail); + break; + + case M5OP_INIT_PARAM: + return invokeSimcall<ABI>(tc, initParam); + + case M5OP_LOAD_SYMBOL: + invokeSimcall<ABI>(tc, loadsymbol); + break; + + case M5OP_RESET_STATS: + invokeSimcall<ABI>(tc, resetstats); + break; + + case M5OP_DUMP_STATS: + invokeSimcall<ABI>(tc, dumpstats); + break; + + case M5OP_DUMP_RESET_STATS: + invokeSimcall<ABI>(tc, dumpresetstats); + break; + + case M5OP_CHECKPOINT: + invokeSimcall<ABI>(tc, m5checkpoint); + break; + + case M5OP_WRITE_FILE: + return invokeSimcall<ABI>(tc, writefile); + + case M5OP_READ_FILE: + return invokeSimcall<ABI>(tc, readfile); + + case M5OP_DEBUG_BREAK: + invokeSimcall<ABI>(tc, debugbreak); + break; + + case M5OP_SWITCH_CPU: + invokeSimcall<ABI>(tc, switchcpu); + break; + + case M5OP_ADD_SYMBOL: + invokeSimcall<ABI>(tc, addsymbol); + break; + + case M5OP_PANIC: + panic("M5 panic instruction called at %s\n", tc->pcState()); + + case M5OP_WORK_BEGIN: + invokeSimcall<ABI>(tc, workbegin); + break; + + case M5OP_WORK_END: + invokeSimcall<ABI>(tc, workend); + break; + + case M5OP_ANNOTATE: + case M5OP_RESERVED2: + case M5OP_RESERVED3: + case M5OP_RESERVED4: + case M5OP_RESERVED5: + warn("Unimplemented m5 op (%#x)\n", func); + break; + + /* SE mode functions */ + case M5OP_SE_SYSCALL: + invokeSimcall<ABI>(tc, m5Syscall); + break; + + case M5OP_SE_PAGE_FAULT: + invokeSimcall<ABI>(tc, TheISA::m5PageFault); + break; + + /* dist-gem5 functions */ + case M5OP_DIST_TOGGLE_SYNC: + invokeSimcall<ABI>(tc, togglesync); + break; + + default: + warn("Unhandled m5 op: %#x\n", func); + break; + } + + return 0; +} + } // namespace PseudoInst #endif // __SIM_PSEUDO_INST_HH__ |