On 8/18/21 6:56 PM, Richard Henderson wrote: > On 8/18/21 6:43 AM, Philippe Mathieu-Daudé wrote: >> The target endianess information is stored in the BigEndian >> bit of the Config0 register in CP0. >> >> As a first step, replace the GET_OFFSET() macro by an inlined >> get_offset() function, passing CPUMIPSState as argument. >> >> Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org> >> --- >> target/mips/tcg/ldst_helper.c | 57 +++++++++++++++++++++-------------- >> 1 file changed, 35 insertions(+), 22 deletions(-) >> >> diff --git a/target/mips/tcg/ldst_helper.c >> b/target/mips/tcg/ldst_helper.c >> index d42812b8a6a..97e7ad7d7a4 100644 >> --- a/target/mips/tcg/ldst_helper.c >> +++ b/target/mips/tcg/ldst_helper.c >> @@ -52,31 +52,44 @@ HELPER_LD_ATOMIC(lld, ldq, 0x7, (target_ulong)) >> #endif /* !CONFIG_USER_ONLY */ >> +static inline bool cpu_is_bigendian(CPUMIPSState *env) >> +{ >> + return extract32(env->CP0_Config0, CP0C0_BE, 1); >> +} >> + >> #ifdef TARGET_WORDS_BIGENDIAN >> #define GET_LMASK(v) ((v) & 3) >> -#define GET_OFFSET(addr, offset) (addr + (offset)) >> #else >> #define GET_LMASK(v) (((v) & 3) ^ 3) >> -#define GET_OFFSET(addr, offset) (addr - (offset)) >> #endif >> +static inline target_ulong get_offset(CPUMIPSState *env, >> + target_ulong addr, int offset) >> +{ >> + if (cpu_is_bigendian(env)) { >> + return addr + offset; >> + } else { >> + return addr - offset; >> + } >> +} >> + >> void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong >> arg2, >> int mem_idx) >> { >> cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, >> GETPC()); >> if (GET_LMASK(arg2) <= 2) { >> - cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> >> 16), >> + cpu_stb_mmuidx_ra(env, get_offset(env, arg2, 1), >> (uint8_t)(arg1 >> 16), >> mem_idx, GETPC()); >> } >> if (GET_LMASK(arg2) <= 1) { >> - cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> >> 8), >> + cpu_stb_mmuidx_ra(env, get_offset(env, arg2, 2), >> (uint8_t)(arg1 >> 8), >> mem_idx, GETPC()); > > So... yes, this is an improvement, but it's now substituting a constant > for a runtime variable many times over.
Oops indeed. > I think you should drop > get_offset() entirely and replace it with > > int dir = cpu_is_bigendian(env) ? 1 : -1; > > stb(env, arg2 + 1 * dir, data); > > stb(env, arg2 + 2 * dir, data); > > Alternately, bite the bullet and split the function(s) into two, > explicitly endian versions: helper_swl_be, helper_swl_le, etc. I'll go for the easier path ;)