* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
*/
#ifndef __SIM_PSEUDO_INST_HH__
class ThreadContext;
-#include "arch/pseudo_inst.hh"
#include "arch/utility.hh"
+#include "base/bitfield.hh"
#include "base/types.hh" // For Tick and Addr data types.
#include "debug/PseudoInst.hh"
#include "sim/guest_abi.hh"
struct PseudoInstABI
{
- using Position = int;
+ using State = int;
};
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)
+ get(ThreadContext *tc, PseudoInstABI::State &state)
{
- return TheISA::getArgument(tc, position, sizeof(uint64_t), false);
+ uint64_t result =
+ TheISA::getArgument(tc, state, sizeof(uint64_t), false);
+ state++;
+ return result;
}
};
void wakeCPU(ThreadContext *tc, uint64_t cpuid);
void m5exit(ThreadContext *tc, Tick delay);
void m5fail(ThreadContext *tc, Tick delay, uint64_t code);
+uint64_t m5sum(ThreadContext *tc, uint64_t a, uint64_t b, uint64_t c,
+ uint64_t d, uint64_t e, uint64_t f);
void resetstats(ThreadContext *tc, Tick delay, Tick period);
void dumpstats(ThreadContext *tc, Tick delay, Tick period);
void dumpresetstats(ThreadContext *tc, Tick delay, Tick period);
void workend(ThreadContext *tc, uint64_t workid, uint64_t threadid);
void m5Syscall(ThreadContext *tc);
void togglesync(ThreadContext *tc);
+void triggerWorkloadEvent(ThreadContext *tc);
/**
* Execute a decoded M5 pseudo instruction
* manner using the ISA-specific getArguments functions.
*
* @param func M5 pseudo op major function number (see utility/m5/m5ops.h)
+ * @param result A reference to a uint64_t to store a result in.
+ * @return Whether the pseudo instruction was recognized/handled.
*/
-template <typename ABI>
-uint64_t
-pseudoInst(ThreadContext *tc, uint8_t func)
+template <typename ABI, bool store_ret>
+bool
+pseudoInstWork(ThreadContext *tc, uint8_t func, uint64_t &result)
{
DPRINTF(PseudoInst, "PseudoInst::pseudoInst(%i)\n", func);
+ result = 0;
+
switch (func) {
case M5OP_ARM:
invokeSimcall<ABI>(tc, arm);
- break;
+ return true;
case M5OP_QUIESCE:
invokeSimcall<ABI>(tc, quiesce);
- break;
+ return true;
case M5OP_QUIESCE_NS:
invokeSimcall<ABI>(tc, quiesceNs);
- break;
+ return true;
case M5OP_QUIESCE_CYCLE:
invokeSimcall<ABI>(tc, quiesceCycles);
- break;
+ return true;
case M5OP_QUIESCE_TIME:
- return invokeSimcall<ABI>(tc, quiesceTime);
+ result = invokeSimcall<ABI, store_ret>(tc, quiesceTime);
+ return true;
case M5OP_RPNS:
- return invokeSimcall<ABI>(tc, rpns);
+ result = invokeSimcall<ABI, store_ret>(tc, rpns);
+ return true;
case M5OP_WAKE_CPU:
invokeSimcall<ABI>(tc, wakeCPU);
- break;
+ return true;
case M5OP_EXIT:
invokeSimcall<ABI>(tc, m5exit);
- break;
+ return true;
case M5OP_FAIL:
invokeSimcall<ABI>(tc, m5fail);
- break;
+ return true;
+
+ // M5OP_SUM is for sanity checking the gem5 op interface.
+ case M5OP_SUM:
+ result = invokeSimcall<ABI, store_ret>(tc, m5sum);
+ return true;
case M5OP_INIT_PARAM:
- return invokeSimcall<ABI>(tc, initParam);
+ result = invokeSimcall<ABI, store_ret>(tc, initParam);
+ return true;
case M5OP_LOAD_SYMBOL:
invokeSimcall<ABI>(tc, loadsymbol);
- break;
+ return true;
case M5OP_RESET_STATS:
invokeSimcall<ABI>(tc, resetstats);
- break;
+ return true;
case M5OP_DUMP_STATS:
invokeSimcall<ABI>(tc, dumpstats);
- break;
+ return true;
case M5OP_DUMP_RESET_STATS:
invokeSimcall<ABI>(tc, dumpresetstats);
- break;
+ return true;
case M5OP_CHECKPOINT:
invokeSimcall<ABI>(tc, m5checkpoint);
- break;
+ return true;
case M5OP_WRITE_FILE:
- return invokeSimcall<ABI>(tc, writefile);
+ result = invokeSimcall<ABI, store_ret>(tc, writefile);
+ return true;
case M5OP_READ_FILE:
- return invokeSimcall<ABI>(tc, readfile);
+ result = invokeSimcall<ABI, store_ret>(tc, readfile);
+ return true;
case M5OP_DEBUG_BREAK:
invokeSimcall<ABI>(tc, debugbreak);
- break;
+ return true;
case M5OP_SWITCH_CPU:
invokeSimcall<ABI>(tc, switchcpu);
- break;
+ return true;
case M5OP_ADD_SYMBOL:
invokeSimcall<ABI>(tc, addsymbol);
- break;
+ return true;
case M5OP_PANIC:
panic("M5 panic instruction called at %s\n", tc->pcState());
case M5OP_WORK_BEGIN:
invokeSimcall<ABI>(tc, workbegin);
- break;
+ return true;
case M5OP_WORK_END:
invokeSimcall<ABI>(tc, workend);
- break;
+ return true;
- case M5OP_ANNOTATE:
+ case M5OP_RESERVED1:
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;
+ return false;
/* dist-gem5 functions */
case M5OP_DIST_TOGGLE_SYNC:
invokeSimcall<ABI>(tc, togglesync);
- break;
+ return true;
+
+ case M5OP_WORKLOAD:
+ invokeSimcall<ABI>(tc, triggerWorkloadEvent);
+ return true;
default:
warn("Unhandled m5 op: %#x\n", func);
- break;
+ return false;
}
+}
- return 0;
+template <typename ABI, bool store_ret=false>
+bool
+pseudoInst(ThreadContext *tc, uint8_t func, uint64_t &result)
+{
+ return pseudoInstWork<ABI, store_ret>(tc, func, result);
+}
+
+template <typename ABI, bool store_ret=true>
+bool
+pseudoInst(ThreadContext *tc, uint8_t func)
+{
+ uint64_t result;
+ return pseudoInstWork<ABI, store_ret>(tc, func, result);
}
} // namespace PseudoInst