On Wed Apr 23, 2025 at 8:09 PM AEST, Ben Dooks wrote:
> In adding a new feature to the riscv target, it turns out the tb_flags
> had already got to the 32-bit limit. Everyone other target has been
> fine with uint32_t (except perhaps arm which does somethng strange to
> extend tb_flags, I think).
>
> To allow extending of tb_flags to be bigger, change the uint32_t to
> a tb_flags_t which a target can define to be bigger (and do this for
> riscv as having tb_flags_t be uint64_t somewhere is necessary to pick
> out bugs in this translation).
>
> This method of extension also stops having to go through each arch
> fixing field usage and anything else that may arise, and given this
> is currently only affecting the tcg, it can be done per target arch.
>
> Note, target/riscv does not currently use any of the other flag bits
> yet. The work is done as we would like to try the big-endian riscv
> again and someone has already taken the last bit we where using at
> (target/riscv/cpu.h#L666 adding PM_SIGNEXTEND where we had BE_DATA)
>
> Q: Do the cpu_get_tb_state calls need uint32_t changing to the
> tb_flag_t as part of this?
>
> Q: As part of this, should we also define a FLAG_DP_TB or similar
> wrapper for the relevant change?
>
> Signed-off-by: Ben Dooks <ben.do...@codethink.co.uk>
> ---
>  accel/tcg/cpu-exec.c      | 10 +++++-----
>  accel/tcg/translate-all.c |  2 +-
>  target/alpha/cpu.h        |  3 ++-
>  target/arm/cpu.h          |  1 +
>  target/avr/cpu.h          |  1 +
>  target/hexagon/cpu.h      |  1 +
>  target/hppa/cpu.h         |  1 +
>  target/i386/cpu.h         |  1 +
>  target/loongarch/cpu.h    |  1 +
>  target/m68k/cpu.h         |  1 +
>  target/microblaze/cpu.h   |  1 +
>  target/mips/cpu.h         |  1 +
>  target/openrisc/cpu.h     |  1 +
>  target/ppc/cpu.h          |  1 +
>  target/riscv/cpu.h        |  3 ++-
>  target/riscv/cpu_helper.c | 40 +++++++++++++++++++--------------------
>  target/rx/cpu.h           |  1 +
>  target/s390x/cpu.h        |  1 +
>  target/sh4/cpu.h          |  1 +
>  target/sparc/cpu.h        |  1 +
>  target/tricore/cpu.h      |  1 +
>  target/xtensa/cpu.h       |  1 +
>  22 files changed, 47 insertions(+), 28 deletions(-)
>
> diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
> index ef3d967e3a..2610ecd40e 100644
> --- a/accel/tcg/cpu-exec.c
> +++ b/accel/tcg/cpu-exec.c
> @@ -302,7 +302,7 @@ static void log_cpu_exec(vaddr pc, CPUState *cpu,
>  }
>  
>  static bool check_for_breakpoints_slow(CPUState *cpu, vaddr pc,
> -                                       uint32_t *cflags)
> +                                       tb_flags_t *cflags)
>  {
>      CPUBreakpoint *bp;
>      bool match_page = false;
> @@ -368,7 +368,7 @@ static bool check_for_breakpoints_slow(CPUState *cpu, 
> vaddr pc,
>  }
>  
>  static inline bool check_for_breakpoints(CPUState *cpu, vaddr pc,
> -                                         uint32_t *cflags)
> +                                         tb_flags_t *cflags)
>  {
>      return unlikely(!QTAILQ_EMPTY(&cpu->breakpoints)) &&
>          check_for_breakpoints_slow(cpu, pc, cflags);
> @@ -388,7 +388,7 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
>      TranslationBlock *tb;
>      vaddr pc;
>      uint64_t cs_base;
> -    uint32_t flags, cflags;
> +    tb_flags_t flags, cflags;

I would leave cflags alone, or at least make a separate patch
for it and type since it's not used the same way.

There is a lot of room in cs_base that most targets don't use.
Could that be customized per target now you are here. Each target
could define a struct type and put what it likes in there. It
would have to provide a compare function as well I guess which
might be a bit slow, so perhaps a default/fallback path that
could be a scalar type and simple inline compare.

Thanks,
Nick

>  
>      /*
>       * By definition we've just finished a TB, so I/O is OK.
> @@ -565,7 +565,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
>      TranslationBlock *tb;
>      vaddr pc;
>      uint64_t cs_base;
> -    uint32_t flags, cflags;
> +    tb_flags_t flags, cflags;
>      int tb_exit;
>  
>      if (sigsetjmp(cpu->jmp_env, 0) == 0) {
> @@ -956,7 +956,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
>              TranslationBlock *tb;
>              vaddr pc;
>              uint64_t cs_base;
> -            uint32_t flags, cflags;
> +            tb_flags_t flags, cflags;
>  
>              cpu_get_tb_cpu_state(cpu_env(cpu), &pc, &cs_base, &flags);
>  
> diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> index 82bc16bd53..ec90a9a9b0 100644
> --- a/accel/tcg/translate-all.c
> +++ b/accel/tcg/translate-all.c
> @@ -594,7 +594,7 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
>          vaddr pc;
>          uint64_t cs_base;
>          tb_page_addr_t addr;
> -        uint32_t flags;
> +        tb_flags_t flags;
>  
>          cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
>          addr = get_page_addr_code(env, pc);
> diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
> index 80562adfb5..25694ede9d 100644
> --- a/target/alpha/cpu.h
> +++ b/target/alpha/cpu.h
> @@ -464,8 +464,9 @@ void alpha_cpu_do_transaction_failed(CPUState *cs, hwaddr 
> physaddr,
>                                       MemTxResult response, uintptr_t 
> retaddr);
>  #endif
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, vaddr *pc,
> -                                        uint64_t *cs_base, uint32_t *pflags)
> +                                        uint64_t *cs_base, tb_flags_t 
> *pflags)
>  {
>      *pc = env->pc;
>      *cs_base = 0;
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index a8177c6c2e..fd32e8d22c 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3151,6 +3151,7 @@ static inline bool bswap_code(bool sctlr_b)
>  #endif
>  }
>  
> +typedef uint32_t tb_flags_t;
>  void cpu_get_tb_cpu_state(CPUARMState *env, vaddr *pc,
>                            uint64_t *cs_base, uint32_t *flags);
>  
> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
> index 06f5ae4d1b..1a3f31b779 100644
> --- a/target/avr/cpu.h
> +++ b/target/avr/cpu.h
> @@ -193,6 +193,7 @@ enum {
>      TB_FLAGS_SKIP = 2,
>  };
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUAVRState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *pflags)
>  {
> diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
> index f78c8f9c2a..c924aa7e91 100644
> --- a/target/hexagon/cpu.h
> +++ b/target/hexagon/cpu.h
> @@ -136,6 +136,7 @@ G_NORETURN void 
> hexagon_raise_exception_err(CPUHexagonState *env,
>                                              uint32_t exception,
>                                              uintptr_t pc);
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
> index 8b36642b59..e56f327737 100644
> --- a/target/hppa/cpu.h
> +++ b/target/hppa/cpu.h
> @@ -352,6 +352,7 @@ hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr);
>  #define CS_BASE_DIFFPAGE    (1 << 12)
>  #define CS_BASE_DIFFSPACE   (1 << 13)
>  
> +typedef uint32_t tb_flags_t;
>  void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
>                            uint64_t *cs_base, uint32_t *pflags);
>  
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 76f24446a5..4283f71d45 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -2612,6 +2612,7 @@ int cpu_mmu_index_kernel(CPUX86State *env);
>  #include "hw/i386/apic.h"
>  #endif
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 254e4fbdcd..48252678c8 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -490,6 +490,7 @@ static inline void set_pc(CPULoongArchState *env, 
> uint64_t value)
>  #define HW_FLAGS_VA32       0x20
>  #define HW_FLAGS_EUEN_ASXE  0x40
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
> index ddb0f29f4a..9787a0611a 100644
> --- a/target/m68k/cpu.h
> +++ b/target/m68k/cpu.h
> @@ -607,6 +607,7 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr 
> physaddr, vaddr addr,
>  #define TB_FLAGS_TRACE          16
>  #define TB_FLAGS_TRACE_BIT      (1 << TB_FLAGS_TRACE)
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUM68KState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
> index e44ddd5307..8b8e312a4f 100644
> --- a/target/microblaze/cpu.h
> +++ b/target/microblaze/cpu.h
> @@ -421,6 +421,7 @@ static inline bool mb_cpu_is_big_endian(CPUState *cs)
>      return !cpu->cfg.endi;
>  }
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUMBState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> index f6877ece8b..e2a6b944ed 100644
> --- a/target/mips/cpu.h
> +++ b/target/mips/cpu.h
> @@ -1368,6 +1368,7 @@ void cpu_mips_clock_init(MIPSCPU *cpu);
>  /* helper.c */
>  target_ulong exception_resume_pc(CPUMIPSState *env);
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
> index b97d2ffdd2..cc923629d4 100644
> --- a/target/openrisc/cpu.h
> +++ b/target/openrisc/cpu.h
> @@ -351,6 +351,7 @@ static inline void cpu_set_gpr(CPUOpenRISCState *env, int 
> i, uint32_t val)
>      env->shadow_gpr[0][i] = val;
>  }
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 3ee83517dc..1575e8584b 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -2755,6 +2755,7 @@ void cpu_write_xer(CPUPPCState *env, target_ulong xer);
>   */
>  #define is_book3s_arch2x(ctx) (!!((ctx)->insns_flags & PPC_SEGMENT_64B))
>  
> +typedef uint32_t tb_flags_t;
>  #ifdef CONFIG_DEBUG_TCG
>  void cpu_get_tb_cpu_state(CPUPPCState *env, vaddr *pc,
>                            uint64_t *cs_base, uint32_t *flags);
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 51e49e03de..5ffa6e6f79 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -808,8 +808,9 @@ static inline uint32_t vext_get_vlmax(uint32_t vlenb, 
> uint32_t vsew,
>      return vlen >> (vsew + 3 - lmul);
>  }
>  
> +typedef uint64_t tb_flags_t;
>  void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
> -                          uint64_t *cs_base, uint32_t *pflags);
> +                          uint64_t *cs_base, tb_flags_t *pflags);
>  
>  bool riscv_cpu_is_32bit(RISCVCPU *cpu);
>  
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6c4391d96b..7d6878fbc3 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -135,7 +135,7 @@ bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, 
> bool virt)
>  }
>  
>  void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
> -                          uint64_t *cs_base, uint32_t *pflags)
> +                          uint64_t *cs_base, tb_flags_t *pflags)
>  {
>      RISCVCPU *cpu = env_archcpu(env);
>      RISCVExtStatus fs, vs;
> @@ -162,18 +162,18 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>          uint32_t maxsz = vlmax << vsew;
>          bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
>                             (maxsz >= 8);
> -        flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
> -        flags = FIELD_DP32(flags, TB_FLAGS, SEW, vsew);
> -        flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
> +        flags = FIELD_DP64(flags, TB_FLAGS, VILL, env->vill);
> +        flags = FIELD_DP64(flags, TB_FLAGS, SEW, vsew);
> +        flags = FIELD_DP64(flags, TB_FLAGS, LMUL,
>                             FIELD_EX64(env->vtype, VTYPE, VLMUL));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
> -        flags = FIELD_DP32(flags, TB_FLAGS, VTA,
> +        flags = FIELD_DP64(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
> +        flags = FIELD_DP64(flags, TB_FLAGS, VTA,
>                             FIELD_EX64(env->vtype, VTYPE, VTA));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VMA,
> +        flags = FIELD_DP64(flags, TB_FLAGS, VMA,
>                             FIELD_EX64(env->vtype, VTYPE, VMA));
> -        flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 
> 0);
> +        flags = FIELD_DP64(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 
> 0);
>      } else {
> -        flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
> +        flags = FIELD_DP64(flags, TB_FLAGS, VILL, 1);
>      }
>  
>      if (cpu_get_fcfien(env)) {
> @@ -182,26 +182,26 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>           * the start of the block is tracked via env->elp. env->elp
>           * is turned on during jalr translation.
>           */
> -        flags = FIELD_DP32(flags, TB_FLAGS, FCFI_LP_EXPECTED, env->elp);
> -        flags = FIELD_DP32(flags, TB_FLAGS, FCFI_ENABLED, 1);
> +        flags = FIELD_DP64(flags, TB_FLAGS, FCFI_LP_EXPECTED, env->elp);
> +        flags = FIELD_DP64(flags, TB_FLAGS, FCFI_ENABLED, 1);
>      }
>  
>      if (cpu_get_bcfien(env)) {
> -        flags = FIELD_DP32(flags, TB_FLAGS, BCFI_ENABLED, 1);
> +        flags = FIELD_DP64(flags, TB_FLAGS, BCFI_ENABLED, 1);
>      }
>  
>  #ifdef CONFIG_USER_ONLY
>      fs = EXT_STATUS_DIRTY;
>      vs = EXT_STATUS_DIRTY;
>  #else
> -    flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
> +    flags = FIELD_DP64(flags, TB_FLAGS, PRIV, env->priv);
>  
>      flags |= riscv_env_mmu_index(env, 0);
>      fs = get_field(env->mstatus, MSTATUS_FS);
>      vs = get_field(env->mstatus, MSTATUS_VS);
>  
>      if (env->virt_enabled) {
> -        flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
> +        flags = FIELD_DP64(flags, TB_FLAGS, VIRT_ENABLED, 1);
>          /*
>           * Merge DISABLED and !DIRTY states using MIN.
>           * We will set both fields when dirtying.
> @@ -221,12 +221,12 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>      }
>  #endif
>  
> -    flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
> -    flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
> -    flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
> -    flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
> -    flags = FIELD_DP32(flags, TB_FLAGS, PM_PMM, riscv_pm_get_pmm(env));
> -    flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
> +    flags = FIELD_DP64(flags, TB_FLAGS, FS, fs);
> +    flags = FIELD_DP64(flags, TB_FLAGS, VS, vs);
> +    flags = FIELD_DP64(flags, TB_FLAGS, XL, env->xl);
> +    flags = FIELD_DP64(flags, TB_FLAGS, AXL, cpu_address_xl(env));
> +    flags = FIELD_DP64(flags, TB_FLAGS, PM_PMM, riscv_pm_get_pmm(env));
> +    flags = FIELD_DP64(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
>  
>      *pflags = flags;
>  }
> diff --git a/target/rx/cpu.h b/target/rx/cpu.h
> index 349d61c4e4..ad4247deec 100644
> --- a/target/rx/cpu.h
> +++ b/target/rx/cpu.h
> @@ -153,6 +153,7 @@ void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int 
> rte);
>  #define RX_CPU_IRQ 0
>  #define RX_CPU_FIR 1
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPURXState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
> index 5b7992deda..a42d412fe6 100644
> --- a/target/s390x/cpu.h
> +++ b/target/s390x/cpu.h
> @@ -417,6 +417,7 @@ static inline int s390x_env_mmu_index(CPUS390XState *env, 
> bool ifetch)
>  
>  #include "tcg/tcg_s390x.h"
>  
> +typedef uint32_t tb_flags_t;
>  void cpu_get_tb_cpu_state(CPUS390XState *env, vaddr *pc,
>                            uint64_t *cs_base, uint32_t *flags);
>  
> diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
> index d536d5d715..b10698f1a9 100644
> --- a/target/sh4/cpu.h
> +++ b/target/sh4/cpu.h
> @@ -382,6 +382,7 @@ static inline void cpu_write_sr(CPUSH4State *env, 
> target_ulong sr)
>      env->sr = sr & ~((1u << SR_M) | (1u << SR_Q) | (1u << SR_T));
>  }
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUSH4State *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
> index 68f8c21e7c..bc876becc9 100644
> --- a/target/sparc/cpu.h
> +++ b/target/sparc/cpu.h
> @@ -745,6 +745,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
>  #define TB_FLAG_FSR_QNE      (1 << 8)
>  #define TB_FLAG_ASI_SHIFT    24
>  
> +typedef uint32_t tb_flags_t;
>  void cpu_get_tb_cpu_state(CPUSPARCState *env, vaddr *pc,
>                            uint64_t *cs_base, uint32_t *pflags);
>  
> diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
> index cf9dbc6df8..917cd9ab5d 100644
> --- a/target/tricore/cpu.h
> +++ b/target/tricore/cpu.h
> @@ -259,6 +259,7 @@ void tricore_tcg_init(void);
>  void tricore_translate_code(CPUState *cs, TranslationBlock *tb,
>                              int *max_insns, vaddr pc, void *host_pc);
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUTriCoreState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {
> diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
> index 8d70bfc0cd..856f794342 100644
> --- a/target/xtensa/cpu.h
> +++ b/target/xtensa/cpu.h
> @@ -733,6 +733,7 @@ static inline uint32_t 
> xtensa_replicate_windowstart(CPUXtensaState *env)
>  
>  #include "exec/cpu-all.h"
>  
> +typedef uint32_t tb_flags_t;
>  static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, vaddr *pc,
>                                          uint64_t *cs_base, uint32_t *flags)
>  {


Reply via email to