mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-10 22:45:36 +00:00
bswap: Add new stn_*_p() and ldn_*_p() memory access functions
There's a common pattern in QEMU where a function needs to perform a data load or store of an N byte integer in a particular endianness. At the moment this is handled by doing a switch() on the size and calling the appropriate ld*_p or st*_p function for each size. Provide a new family of functions ldn_*_p() and stn_*_p() which take the size as an argument and do the switch() themselves. Backports commit afa4f6653dca095f63f3fe7f2001e9334f5676c1 from qemu
This commit is contained in:
parent
61a7ac6948
commit
8295b228e3
|
@ -166,6 +166,8 @@ static inline void tswap64s(uint64_t *s)
|
||||||
#define stq_p(p, v) stq_be_p(p, v)
|
#define stq_p(p, v) stq_be_p(p, v)
|
||||||
#define stfl_p(p, v) stfl_be_p(p, v)
|
#define stfl_p(p, v) stfl_be_p(p, v)
|
||||||
#define stfq_p(p, v) stfq_be_p(p, v)
|
#define stfq_p(p, v) stfq_be_p(p, v)
|
||||||
|
#define ldn_p(p, sz) ldn_be_p(p, sz)
|
||||||
|
#define stn_p(p, sz, v) stn_be_p(p, sz, v)
|
||||||
#else
|
#else
|
||||||
#define lduw_p(p) lduw_le_p(p)
|
#define lduw_p(p) lduw_le_p(p)
|
||||||
#define ldsw_p(p) ldsw_le_p(p)
|
#define ldsw_p(p) ldsw_le_p(p)
|
||||||
|
@ -178,6 +180,8 @@ static inline void tswap64s(uint64_t *s)
|
||||||
#define stq_p(p, v) stq_le_p(p, v)
|
#define stq_p(p, v) stq_le_p(p, v)
|
||||||
#define stfl_p(p, v) stfl_le_p(p, v)
|
#define stfl_p(p, v) stfl_le_p(p, v)
|
||||||
#define stfq_p(p, v) stfq_le_p(p, v)
|
#define stfq_p(p, v) stfq_le_p(p, v)
|
||||||
|
#define ldn_p(p, sz) ldn_le_p(p, sz)
|
||||||
|
#define stn_p(p, sz, v) stn_le_p(p, sz, v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* MMU memory access macros */
|
/* MMU memory access macros */
|
||||||
|
|
|
@ -266,6 +266,23 @@ typedef union {
|
||||||
* be : big endian
|
* be : big endian
|
||||||
* le : little endian
|
* le : little endian
|
||||||
* (except for byte accesses, which have no endian infix).
|
* (except for byte accesses, which have no endian infix).
|
||||||
|
*
|
||||||
|
* The target endian accessors are obviously only available to source
|
||||||
|
* files which are built per-target; they are defined in cpu-all.h.
|
||||||
|
*
|
||||||
|
* In all cases these functions take a host pointer.
|
||||||
|
* For accessors that take a guest address rather than a
|
||||||
|
* host address, see the cpu_{ld,st}_* accessors defined in
|
||||||
|
* cpu_ldst.h.
|
||||||
|
*
|
||||||
|
* For cases where the size to be used is not fixed at compile time,
|
||||||
|
* there are
|
||||||
|
* stn{endian}_p(ptr, sz, val)
|
||||||
|
* which stores @val to @ptr as an @endian-order number @sz bytes in size
|
||||||
|
* and
|
||||||
|
* ldn{endian}_p(ptr, sz)
|
||||||
|
* which loads @sz bytes from @ptr as an unsigned @endian-order number
|
||||||
|
* and returns it in a uint64_t.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline int ldub_p(const void *ptr)
|
static inline int ldub_p(const void *ptr)
|
||||||
|
@ -471,6 +488,49 @@ static inline unsigned long leul_to_cpu(unsigned long v)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store v to p as a sz byte value in host order */
|
||||||
|
#define DO_STN_LDN_P(END) \
|
||||||
|
static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \
|
||||||
|
{ \
|
||||||
|
switch (sz) { \
|
||||||
|
case 1: \
|
||||||
|
stb_p(ptr, v); \
|
||||||
|
break; \
|
||||||
|
case 2: \
|
||||||
|
stw_ ## END ## _p(ptr, v); \
|
||||||
|
break; \
|
||||||
|
case 4: \
|
||||||
|
stl_ ## END ## _p(ptr, v); \
|
||||||
|
break; \
|
||||||
|
case 8: \
|
||||||
|
stq_ ## END ## _p(ptr, v); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
g_assert_not_reached(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \
|
||||||
|
{ \
|
||||||
|
switch (sz) { \
|
||||||
|
case 1: \
|
||||||
|
return ldub_p(ptr); \
|
||||||
|
case 2: \
|
||||||
|
return lduw_ ## END ## _p(ptr); \
|
||||||
|
case 4: \
|
||||||
|
return (uint32_t)ldl_ ## END ## _p(ptr); \
|
||||||
|
case 8: \
|
||||||
|
return ldq_ ## END ## _p(ptr); \
|
||||||
|
default: \
|
||||||
|
g_assert_not_reached(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
DO_STN_LDN_P(he)
|
||||||
|
DO_STN_LDN_P(le)
|
||||||
|
DO_STN_LDN_P(be)
|
||||||
|
|
||||||
|
#undef DO_STN_LDN_P
|
||||||
|
|
||||||
#undef le_bswap
|
#undef le_bswap
|
||||||
#undef be_bswap
|
#undef be_bswap
|
||||||
#undef le_bswaps
|
#undef le_bswaps
|
||||||
|
|
Loading…
Reference in a new issue