summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/kvm/arm_cpu.cc5
-rw-r--r--src/arch/generic/mmapped_ipr.cc2
-rw-r--r--src/sim/pseudo_inst.cc144
-rw-r--r--src/sim/pseudo_inst.hh188
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__