softmmu: add helper function to pass through retaddr

This patch introduces several helpers to pass return address
which points to the TB. Correct return address allows correct
restoring of the guest PC and icount. These functions should be used when
helpers embedded into TB invoke memory operations.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Message-Id: <20150710095650.13280.32255.stgit@PASHA-ISP>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Pavel Dovgalyuk 2015-07-10 12:56:50 +03:00 committed by Richard Henderson
parent 97ed5ccdee
commit 282dffc8a4
4 changed files with 99 additions and 14 deletions

View File

@ -27,20 +27,24 @@
#define SUFFIX q #define SUFFIX q
#define USUFFIX q #define USUFFIX q
#define DATA_TYPE uint64_t #define DATA_TYPE uint64_t
#define SHIFT 3
#elif DATA_SIZE == 4 #elif DATA_SIZE == 4
#define SUFFIX l #define SUFFIX l
#define USUFFIX l #define USUFFIX l
#define DATA_TYPE uint32_t #define DATA_TYPE uint32_t
#define SHIFT 2
#elif DATA_SIZE == 2 #elif DATA_SIZE == 2
#define SUFFIX w #define SUFFIX w
#define USUFFIX uw #define USUFFIX uw
#define DATA_TYPE uint16_t #define DATA_TYPE uint16_t
#define DATA_STYPE int16_t #define DATA_STYPE int16_t
#define SHIFT 1
#elif DATA_SIZE == 1 #elif DATA_SIZE == 1
#define SUFFIX b #define SUFFIX b
#define USUFFIX ub #define USUFFIX ub
#define DATA_TYPE uint8_t #define DATA_TYPE uint8_t
#define DATA_STYPE int8_t #define DATA_STYPE int8_t
#define SHIFT 0
#else #else
#error unsupported data size #error unsupported data size
#endif #endif
@ -54,27 +58,36 @@
#ifdef SOFTMMU_CODE_ACCESS #ifdef SOFTMMU_CODE_ACCESS
#define ADDR_READ addr_code #define ADDR_READ addr_code
#define MMUSUFFIX _cmmu #define MMUSUFFIX _cmmu
#define URETSUFFIX SUFFIX
#define SRETSUFFIX SUFFIX
#else #else
#define ADDR_READ addr_read #define ADDR_READ addr_read
#define MMUSUFFIX _mmu #define MMUSUFFIX _mmu
#define URETSUFFIX USUFFIX
#define SRETSUFFIX glue(s, SUFFIX)
#endif #endif
/* generic load/store macros */ /* generic load/store macros */
static inline RES_TYPE static inline RES_TYPE
glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
target_ulong ptr,
uintptr_t retaddr)
{ {
int page_index; int page_index;
RES_TYPE res; RES_TYPE res;
target_ulong addr; target_ulong addr;
int mmu_idx; int mmu_idx;
TCGMemOpIdx oi;
addr = ptr; addr = ptr;
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = CPU_MMU_INDEX; mmu_idx = CPU_MMU_INDEX;
if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx); oi = make_memop_idx(SHIFT, mmu_idx);
res = glue(glue(helper_ret_ld, URETSUFFIX), MMUSUFFIX)(env, addr,
oi, retaddr);
} else { } else {
uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
res = glue(glue(ld, USUFFIX), _p)((uint8_t *)hostaddr); res = glue(glue(ld, USUFFIX), _p)((uint8_t *)hostaddr);
@ -82,27 +95,43 @@ glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
return res; return res;
} }
static inline RES_TYPE
glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
{
return glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(env, ptr, 0);
}
#if DATA_SIZE <= 2 #if DATA_SIZE <= 2
static inline int static inline int
glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
target_ulong ptr,
uintptr_t retaddr)
{ {
int res, page_index; int res, page_index;
target_ulong addr; target_ulong addr;
int mmu_idx; int mmu_idx;
TCGMemOpIdx oi;
addr = ptr; addr = ptr;
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = CPU_MMU_INDEX; mmu_idx = CPU_MMU_INDEX;
if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX), oi = make_memop_idx(SHIFT, mmu_idx);
MMUSUFFIX)(env, addr, mmu_idx); res = (DATA_STYPE)glue(glue(helper_ret_ld, SRETSUFFIX),
MMUSUFFIX)(env, addr, oi, retaddr);
} else { } else {
uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
res = glue(glue(lds, SUFFIX), _p)((uint8_t *)hostaddr); res = glue(glue(lds, SUFFIX), _p)((uint8_t *)hostaddr);
} }
return res; return res;
} }
static inline int
glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
{
return glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(env, ptr, 0);
}
#endif #endif
#ifndef SOFTMMU_CODE_ACCESS #ifndef SOFTMMU_CODE_ACCESS
@ -110,25 +139,36 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
/* generic store macro */ /* generic store macro */
static inline void static inline void
glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
RES_TYPE v) target_ulong ptr,
RES_TYPE v, uintptr_t retaddr)
{ {
int page_index; int page_index;
target_ulong addr; target_ulong addr;
int mmu_idx; int mmu_idx;
TCGMemOpIdx oi;
addr = ptr; addr = ptr;
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = CPU_MMU_INDEX; mmu_idx = CPU_MMU_INDEX;
if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx); oi = make_memop_idx(SHIFT, mmu_idx);
glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, v, oi,
retaddr);
} else { } else {
uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
glue(glue(st, SUFFIX), _p)((uint8_t *)hostaddr, v); glue(glue(st, SUFFIX), _p)((uint8_t *)hostaddr, v);
} }
} }
static inline void
glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
RES_TYPE v)
{
glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(env, ptr, v, 0);
}
#endif /* !SOFTMMU_CODE_ACCESS */ #endif /* !SOFTMMU_CODE_ACCESS */
#undef RES_TYPE #undef RES_TYPE
@ -139,3 +179,6 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
#undef DATA_SIZE #undef DATA_SIZE
#undef MMUSUFFIX #undef MMUSUFFIX
#undef ADDR_READ #undef ADDR_READ
#undef URETSUFFIX
#undef SRETSUFFIX
#undef SHIFT

View File

@ -56,12 +56,28 @@ glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
return glue(glue(ld, USUFFIX), _p)(g2h(ptr)); return glue(glue(ld, USUFFIX), _p)(g2h(ptr));
} }
static inline RES_TYPE
glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
target_ulong ptr,
uintptr_t retaddr)
{
return glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(env, ptr);
}
#if DATA_SIZE <= 2 #if DATA_SIZE <= 2
static inline int static inline int
glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
{ {
return glue(glue(lds, SUFFIX), _p)(g2h(ptr)); return glue(glue(lds, SUFFIX), _p)(g2h(ptr));
} }
static inline int
glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
target_ulong ptr,
uintptr_t retaddr)
{
return glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(env, ptr);
}
#endif #endif
#ifndef CODE_ACCESS #ifndef CODE_ACCESS
@ -71,6 +87,15 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
{ {
glue(glue(st, SUFFIX), _p)(g2h(ptr), v); glue(glue(st, SUFFIX), _p)(g2h(ptr), v);
} }
static inline void
glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
target_ulong ptr,
RES_TYPE v,
uintptr_t retaddr)
{
glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(env, ptr, v);
}
#endif #endif
#undef RES_TYPE #undef RES_TYPE

View File

@ -165,9 +165,6 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
} }
#endif #endif
#ifdef SOFTMMU_CODE_ACCESS
static __attribute__((unused))
#endif
WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr) TCGMemOpIdx oi, uintptr_t retaddr)
{ {
@ -252,9 +249,6 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
} }
#if DATA_SIZE > 1 #if DATA_SIZE > 1
#ifdef SOFTMMU_CODE_ACCESS
static __attribute__((unused))
#endif
WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr) TCGMemOpIdx oi, uintptr_t retaddr)
{ {

View File

@ -986,25 +986,48 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
TCGMemOpIdx oi, uintptr_t retaddr); TCGMemOpIdx oi, uintptr_t retaddr);
uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
uint32_t helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
uint64_t helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
uint32_t helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr);
/* Temporary aliases until backends are converted. */ /* Temporary aliases until backends are converted. */
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
# define helper_ret_ldsw_mmu helper_be_ldsw_mmu # define helper_ret_ldsw_mmu helper_be_ldsw_mmu
# define helper_ret_lduw_mmu helper_be_lduw_mmu # define helper_ret_lduw_mmu helper_be_lduw_mmu
# define helper_ret_ldsl_mmu helper_be_ldsl_mmu # define helper_ret_ldsl_mmu helper_be_ldsl_mmu
# define helper_ret_ldul_mmu helper_be_ldul_mmu # define helper_ret_ldul_mmu helper_be_ldul_mmu
# define helper_ret_ldl_mmu helper_be_ldul_mmu
# define helper_ret_ldq_mmu helper_be_ldq_mmu # define helper_ret_ldq_mmu helper_be_ldq_mmu
# define helper_ret_stw_mmu helper_be_stw_mmu # define helper_ret_stw_mmu helper_be_stw_mmu
# define helper_ret_stl_mmu helper_be_stl_mmu # define helper_ret_stl_mmu helper_be_stl_mmu
# define helper_ret_stq_mmu helper_be_stq_mmu # define helper_ret_stq_mmu helper_be_stq_mmu
# define helper_ret_ldw_cmmu helper_be_ldw_cmmu
# define helper_ret_ldl_cmmu helper_be_ldl_cmmu
# define helper_ret_ldq_cmmu helper_be_ldq_cmmu
#else #else
# define helper_ret_ldsw_mmu helper_le_ldsw_mmu # define helper_ret_ldsw_mmu helper_le_ldsw_mmu
# define helper_ret_lduw_mmu helper_le_lduw_mmu # define helper_ret_lduw_mmu helper_le_lduw_mmu
# define helper_ret_ldsl_mmu helper_le_ldsl_mmu # define helper_ret_ldsl_mmu helper_le_ldsl_mmu
# define helper_ret_ldul_mmu helper_le_ldul_mmu # define helper_ret_ldul_mmu helper_le_ldul_mmu
# define helper_ret_ldl_mmu helper_le_ldul_mmu
# define helper_ret_ldq_mmu helper_le_ldq_mmu # define helper_ret_ldq_mmu helper_le_ldq_mmu
# define helper_ret_stw_mmu helper_le_stw_mmu # define helper_ret_stw_mmu helper_le_stw_mmu
# define helper_ret_stl_mmu helper_le_stl_mmu # define helper_ret_stl_mmu helper_le_stl_mmu
# define helper_ret_stq_mmu helper_le_stq_mmu # define helper_ret_stq_mmu helper_le_stq_mmu
# define helper_ret_ldw_cmmu helper_le_ldw_cmmu
# define helper_ret_ldl_cmmu helper_le_ldl_cmmu
# define helper_ret_ldq_cmmu helper_le_ldq_cmmu
#endif #endif
#endif /* CONFIG_SOFTMMU */ #endif /* CONFIG_SOFTMMU */