diff --git a/src/sim/guest_abi.hh b/src/sim/guest_abi.hh index 2dd27c424e..5432af3f92 100644 --- a/src/sim/guest_abi.hh +++ b/src/sim/guest_abi.hh @@ -61,6 +61,32 @@ namespace GuestABI * std::enable_if style conditional specializations. */ +/* + * Position may need to be initialized based on the ThreadContext, for instance + * to find out where the stack pointer is initially. + */ +template +struct PositionInitializer +{ + static typename ABI::Position + init(const ThreadContext *tc) + { + return typename ABI::Position(); + } +}; + +template +struct PositionInitializer::value + >::type> +{ + static typename ABI::Position + init(const ThreadContext *tc) + { + return typename ABI::Position(tc); + } +}; + template struct Result { @@ -407,7 +433,7 @@ invokeSimcall(ThreadContext *tc, { // Default construct a Position to track consumed resources. Built in // types will be zero initialized. - auto position = typename ABI::Position(); + auto position = GuestABI::PositionInitializer::init(tc); GuestABI::ResultAllocator::allocate(tc, position); return GuestABI::callFrom(tc, position, target); } @@ -427,7 +453,7 @@ invokeSimcall(ThreadContext *tc, { // Default construct a Position to track consumed resources. Built in // types will be zero initialized. - auto position = typename ABI::Position(); + auto position = GuestABI::PositionInitializer::init(tc); GuestABI::callFrom(tc, position, target); } @@ -450,7 +476,7 @@ dumpSimcall(std::string name, ThreadContext *tc, std::function target= std::function()) { - auto position = typename ABI::Position(); + auto position = GuestABI::PositionInitializer::init(tc); std::ostringstream ss; GuestABI::ResultAllocator::allocate(tc, position); diff --git a/src/sim/guest_abi.test.cc b/src/sim/guest_abi.test.cc index 2f896f9b3e..506163ee65 100644 --- a/src/sim/guest_abi.test.cc +++ b/src/sim/guest_abi.test.cc @@ -46,6 +46,8 @@ class ThreadContext int intResult = DefaultIntResult; double floatResult = DefaultFloatResult; + + int intOffset = 0; }; const int ThreadContext::ints[] = { @@ -80,6 +82,15 @@ struct TestABI_2D using Position = std::pair; }; +struct TestABI_TcInit +{ + struct Position + { + int pos; + Position(const ThreadContext *tc) : pos(tc->intOffset) {} + }; +}; + namespace GuestABI { @@ -188,6 +199,17 @@ struct Result +struct Argument +{ + static int + get(ThreadContext *tc, TestABI_TcInit::Position &position) + { + return tc->ints[position.pos++]; + } +}; + } // namespace GuestABI // Test function which verifies that its arguments reflect the 1D ABI and @@ -237,6 +259,13 @@ test2DVoid(ThreadContext *tc, int a, float b, int c, double d, EXPECT_EQ(varargs.get(), tc->floats[3]); } +void +testTcInit(ThreadContext *tc, int a) +{ + EXPECT_EQ(tc->intOffset, 2); + EXPECT_EQ(a, tc->ints[2]); +} + // Test functions which returns various types of values. const int IntRetValue = 50; const float FloatRetValue = 3.14; @@ -271,6 +300,13 @@ TEST(GuestABI, ABI_2D_args) EXPECT_EQ(tc.floatResult, tc.DefaultFloatResult); } +TEST(GuestABI, ABI_TC_init) +{ + ThreadContext tc; + tc.intOffset = 2; + invokeSimcall(&tc, testTcInit); +} + TEST(GuestABI, ABI_returns) { // 1D returns.