@samitouri / QOSamiQemu / commits / 5389bbea68

target/hexagon: Add new macro definitions for sysemu

Also: add nop TCG overrides for break, unpause, fetchbo; add TCG override for dczeroa_nt (non-temporal variant of dczeroa). break: this hardware breakpoint instruction is used with the in-silicon debugger feature, this is not modeled. unpause: this instruction is used to resume hardware threads that are stalled by pause instructions. pause is modeled as a nop, or in RR mode as an EXCP_YIELD. This instruction is safe to ignore. Since prefetch functions are not modeled, fetchbo is safe to ignore. Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Brian Cain committed Jun 22, 2026 at 15:28 UTC 5389bbea68a1c106246e0e96b3520a3ad45c03d7
4 files changed +276 -1
target/hexagon/gen_tcg.h
+9
@@ -488,6 +488,7 @@
488
489 /* dczeroa clears the 32 byte cache line at the address given */
490 #define fGEN_TCG_Y2_dczeroa(SHORTCODE) SHORTCODE
491 +#define fGEN_TCG_Y2_dczeroa_nt(SHORTCODE) SHORTCODE
492
493 /* In linux-user mode, these are not modelled, suppress compiler warning */
494 #define fGEN_TCG_Y2_dcinva(SHORTCODE) \
@@ -1112,6 +1113,9 @@
1113 RdV, tcg_constant_tl(0)); \
1114 } while (0)
1115
1116 +#define fGEN_TCG_Y2_break(SHORTCODE)
1117 +#define fGEN_TCG_J2_unpause(SHORTCODE)
1118 +
1119 #define fGEN_TCG_J2_pause(SHORTCODE) \
1120 do { \
1121 uiV = uiV; \
@@ -1321,6 +1325,11 @@
1325 RsV = RsV; \
1326 uiV = uiV; \
1327 } while (0)
1328 +#define fGEN_TCG_Y2_dcfetchbo_nt(SHORTCODE) \
1329 + do { \
1330 + RsV = RsV; \
1331 + uiV = uiV; \
1332 + } while (0)
1333
1334 #define fGEN_TCG_L2_loadw_aq(SHORTCODE) SHORTCODE
1335 #define fGEN_TCG_L4_loadd_aq(SHORTCODE) SHORTCODE
target/hexagon/macros.h
+24 -1
@@ -631,8 +631,18 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
631 #define fCONSTLL(A) A##LL
632 #define fECHO(A) (A)
633
634 -#define fTRAP(TRAPTYPE, IMM) helper_raise_exception(env, HEX_EXCP_TRAP0)
634 +#ifdef CONFIG_USER_ONLY
635 +#define fTRAP(TRAPTYPE, IMM) \
636 + do { \
637 + hexagon_raise_exception_err(env, HEX_EVENT_TRAP0, PC); \
638 + } while (0)
639 +#endif
640 +
641 +#define fDO_TRACE(SREG)
642 +#define fBREAK()
643 +#define fUNPAUSE()
644 #define fPAUSE(IMM)
645 +#define fDCFETCH(REG)
646
647 #define fALIGN_REG_FIELD_VALUE(FIELD, VAL) \
648 ((VAL) << reg_field_info[FIELD].offset)
@@ -654,5 +664,18 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
664 #define fBRANCH_SPECULATE_STALL(DOTNEWVAL, JUMP_COND, SPEC_DIR, HINTBITNUM, \
665 STRBITNUM) /* Nothing */
666
667 +#ifdef CONFIG_USER_ONLY
668 +/*
669 + * This macro can only be true in guest mode.
670 + * In user mode, the 4 VIRTINSN's can't be reached
671 + */
672 +#define fTRAP1_VIRTINSN(IMM) (false)
673 +#define fVIRTINSN_SPSWAP(IMM, REG) g_assert_not_reached()
674 +#define fVIRTINSN_GETIE(IMM, REG) g_assert_not_reached()
675 +#define fVIRTINSN_SETIE(IMM, REG) g_assert_not_reached()
676 +#define fVIRTINSN_RTE(IMM, REG) g_assert_not_reached()
677 +#endif
678 +
679 +#define fPREDUSE_TIMING()
680
681 #endif
target/hexagon/op_helper.c
+4
@@ -25,6 +25,7 @@
25 #include "cpu.h"
26 #include "internal.h"
27 #include "macros.h"
28 +#include "sys_macros.h"
29 #include "arch.h"
30 #include "hex_arch_types.h"
31 #include "fma_emu.h"
@@ -32,6 +33,9 @@
33 #include "mmvec/macros.h"
34 #include "op_helper.h"
35 #include "translate.h"
36 +#ifndef CONFIG_USER_ONLY
37 +#include "hexswi.h"
38 +#endif
39
40 #define SF_BIAS 127
41 #define SF_MANTBITS 23
target/hexagon/sys_macros.h new
+239
@@ -0,0 +1,239 @@
1 +/*
2 + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3 + *
4 + * SPDX-License-Identifier: GPL-2.0-or-later
5 + */
6 +
7 +#ifndef HEXAGON_SYS_MACROS_H
8 +#define HEXAGON_SYS_MACROS_H
9 +
10 +/*
11 + * Macro definitions for Hexagon system mode
12 + */
13 +
14 +#ifndef CONFIG_USER_ONLY
15 +
16 +#include "system/physmem.h"
17 +
18 +#ifdef QEMU_GENERATE
19 +#define GET_SSR_FIELD(RES, FIELD) \
20 + GET_FIELD(RES, FIELD, hex_t_sreg[HEX_SREG_SSR])
21 +#else
22 +
23 +#define GET_SSR_FIELD(FIELD, REGIN) \
24 + (uint32_t)GET_FIELD(FIELD, REGIN)
25 +#define GET_SYSCFG_FIELD(FIELD, REGIN) \
26 + (uint32_t)GET_FIELD(FIELD, REGIN)
27 +#define SET_SYSTEM_FIELD(ENV, REG, FIELD, VAL) \
28 + do { \
29 + HexagonCPU *_sf_cpu = env_archcpu(ENV); \
30 + uint32_t regval; \
31 + if ((REG) < HEX_SREG_GLB_START) { \
32 + regval = (ENV)->t_sreg[(REG)]; \
33 + } else { \
34 + regval = _sf_cpu->globalregs ? \
35 + hexagon_globalreg_read(_sf_cpu->globalregs, (REG), \
36 + (ENV)->threadId) : 0; \
37 + } \
38 + fINSERT_BITS(regval, reg_field_info[FIELD].width, \
39 + reg_field_info[FIELD].offset, (VAL)); \
40 + if ((REG) < HEX_SREG_GLB_START) { \
41 + (ENV)->t_sreg[(REG)] = regval; \
42 + } else if (_sf_cpu->globalregs) { \
43 + hexagon_globalreg_write(_sf_cpu->globalregs, (REG), regval, \
44 + (ENV)->threadId); \
45 + } \
46 + } while (0)
47 +#define SET_SSR_FIELD(ENV, FIELD, VAL) \
48 + SET_SYSTEM_FIELD(ENV, HEX_SREG_SSR, FIELD, VAL)
49 +#define SET_SYSCFG_FIELD(ENV, FIELD, VAL) \
50 + SET_SYSTEM_FIELD(ENV, HEX_SREG_SYSCFG, FIELD, VAL)
51 +
52 +#define CCR_FIELD_SET(ENV, FIELD) \
53 + (!!GET_FIELD(FIELD, (ENV)->t_sreg[HEX_SREG_CCR]))
54 +
55 +/*
56 + * Direct-to-guest is not implemented yet, continuing would cause unexpected
57 + * behavior, so we abort.
58 + */
59 +#define ASSERT_DIRECT_TO_GUEST_UNSET(ENV, EXCP) \
60 + do { \
61 + switch (EXCP) { \
62 + case HEX_EVENT_TRAP0: \
63 + g_assert(!CCR_FIELD_SET(ENV, CCR_GTE)); \
64 + break; \
65 + case HEX_EVENT_IMPRECISE: \
66 + case HEX_EVENT_PRECISE: \
67 + case HEX_EVENT_FPTRAP: \
68 + g_assert(!CCR_FIELD_SET(ENV, CCR_GEE)); \
69 + break; \
70 + default: \
71 + if ((EXCP) >= HEX_EVENT_INT0) { \
72 + g_assert(!CCR_FIELD_SET(ENV, CCR_GIE)); \
73 + } \
74 + break; \
75 + } \
76 + } while (0)
77 +#endif
78 +
79 +#define fREAD_ELR() (env->t_sreg[HEX_SREG_ELR])
80 +
81 +#define fLOAD_PHYS(NUM, SIZE, SIGN, SRC1, SRC2, DST) { \
82 + const uintptr_t rs = ((unsigned long)(unsigned)(SRC1)) & 0x7ff; \
83 + const uintptr_t rt = ((unsigned long)(unsigned)(SRC2)) << 11; \
84 + const uintptr_t addr = rs + rt; \
85 + physical_memory_read(addr, &DST, sizeof(uint32_t)); \
86 +}
87 +
88 +#define fPOW2_HELP_ROUNDUP(VAL) \
89 + ((VAL) | \
90 + ((VAL) >> 1) | \
91 + ((VAL) >> 2) | \
92 + ((VAL) >> 4) | \
93 + ((VAL) >> 8) | \
94 + ((VAL) >> 16))
95 +#define fPOW2_ROUNDUP(VAL) (fPOW2_HELP_ROUNDUP((VAL) - 1) + 1)
96 +
97 +#define fTRAP(TRAPTYPE, IMM) \
98 + register_trap_exception(env, TRAPTYPE, IMM, PC)
99 +
100 +#define fVIRTINSN_SPSWAP(IMM, REG)
101 +#define fVIRTINSN_GETIE(IMM, REG) { REG = 0xdeafbeef; }
102 +#define fVIRTINSN_SETIE(IMM, REG)
103 +#define fVIRTINSN_RTE(IMM, REG)
104 +#define fGRE_ENABLED() \
105 + GET_FIELD(CCR_GRE, env->t_sreg[HEX_SREG_CCR])
106 +#define fTRAP1_VIRTINSN(IMM) \
107 + (fGRE_ENABLED() && \
108 + (((IMM) == 1) || ((IMM) == 3) || ((IMM) == 4) || ((IMM) == 6)))
109 +
110 +/* Not modeled in qemu */
111 +
112 +#define MARK_LATE_PRED_WRITE(RNUM)
113 +#define fICINVIDX(REG)
114 +#define fICKILL()
115 +#define fDCKILL()
116 +#define fL2KILL()
117 +#define fL2UNLOCK()
118 +#define fL2CLEAN()
119 +#define fL2CLEANINV()
120 +#define fL2CLEANPA(REG)
121 +#define fL2CLEANINVPA(REG)
122 +#define fL2CLEANINVIDX(REG)
123 +#define fL2CLEANIDX(REG)
124 +#define fL2INVIDX(REG)
125 +#define fL2TAGR(INDEX, DST, DSTREG)
126 +#define fL2UNLOCKA(VA) ((void) VA)
127 +#define fL2TAGW(INDEX, PART2)
128 +#define fDCCLEANIDX(REG)
129 +#define fDCCLEANINVIDX(REG)
130 +
131 +/* Always succeed: */
132 +#define fL2LOCKA(EA, PDV, PDN) ((void) EA, PDV = 0xFF)
133 +#define fCLEAR_RTE_EX() \
134 + do { \
135 + uint32_t tmp = env->t_sreg[HEX_SREG_SSR]; \
136 + fINSERT_BITS(tmp, reg_field_info[SSR_EX].width, \
137 + reg_field_info[SSR_EX].offset, 0); \
138 + log_sreg_write(env, HEX_SREG_SSR, tmp, slot); \
139 + } while (0)
140 +
141 +#define fDCINVIDX(REG)
142 +#define fDCINVA(REG) do { REG = REG; } while (0) /* Nothing to do in qemu */
143 +
144 +#define fTLB_IDXMASK(INDEX) \
145 + ((INDEX) & (fPOW2_ROUNDUP( \
146 + fCAST4u(hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))) - 1))
147 +
148 +#define fTLB_NONPOW2WRAP(INDEX) \
149 + (((INDEX) >= hexagon_tlb_get_num_entries(env_archcpu(env)->tlb)) ? \
150 + ((INDEX) - hexagon_tlb_get_num_entries(env_archcpu(env)->tlb)) : \
151 + (INDEX))
152 +
153 +
154 +#define fTLBW(INDEX, VALUE) \
155 + hex_tlbw(env, (INDEX), (VALUE))
156 +#define fTLBW_EXTENDED(INDEX, VALUE) \
157 + hex_tlbw(env, (INDEX), (VALUE))
158 +#define fTLB_ENTRY_OVERLAP(VALUE) \
159 + (hex_tlb_check_overlap(env, VALUE, -1) != -2)
160 +#define fTLB_ENTRY_OVERLAP_IDX(VALUE) \
161 + hex_tlb_check_overlap(env, VALUE, -1)
162 +#define fTLBR(INDEX) \
163 + hexagon_tlb_read(env_archcpu(env)->tlb, \
164 + fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX)))
165 +#define fTLBR_EXTENDED(INDEX) \
166 + hexagon_tlb_read(env_archcpu(env)->tlb, \
167 + fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX)))
168 +#define fTLBP(TLBHI) \
169 + hex_tlb_lookup(env, ((TLBHI) >> 12), ((TLBHI) << 12))
170 +#define iic_flush_cache(p)
171 +
172 +#define fIN_DEBUG_MODE(TNUM) ({ \
173 + HexagonCPU *_cpu = env_archcpu(env); \
174 + uint32_t _isdbst = _cpu->globalregs ? \
175 + hexagon_globalreg_read(_cpu->globalregs, \
176 + HEX_SREG_ISDBST, env->threadId) : 0; \
177 + (GET_FIELD(ISDBST_DEBUGMODE, _isdbst) \
178 + & (0x1 << (TNUM))) != 0; })
179 +
180 +#define fIN_DEBUG_MODE_NO_ISDB(TNUM) false
181 +#define fIN_DEBUG_MODE_WARN(TNUM) false
182 +
183 +#ifdef QEMU_GENERATE
184 +
185 +/*
186 + * Read tags back as zero for now:
187 + *
188 + * tag value in RD[31:10] for 32k, RD[31:9] for 16k
189 + */
190 +#define fICTAGR(RS, RD, RD2) \
191 + do { \
192 + RD = ctx->zero; \
193 + } while (0)
194 +#define fICTAGW(RS, RD)
195 +#define fICDATAR(RS, RD) \
196 + do { \
197 + RD = ctx->zero; \
198 + } while (0)
199 +#define fICDATAW(RS, RD)
200 +
201 +#define fDCTAGW(RS, RT)
202 +/* tag: RD[23:0], state: RD[30:29] */
203 +#define fDCTAGR(INDEX, DST, DST_REG_NUM) \
204 + do { \
205 + DST = ctx->zero; \
206 + } while (0)
207 +#else
208 +
209 +/*
210 + * Read tags back as zero for now:
211 + *
212 + * tag value in RD[31:10] for 32k, RD[31:9] for 16k
213 + */
214 +#define fICTAGR(RS, RD, RD2) \
215 + do { \
216 + RD = 0x00; \
217 + } while (0)
218 +#define fICTAGW(RS, RD)
219 +#define fICDATAR(RS, RD) \
220 + do { \
221 + RD = 0x00; \
222 + } while (0)
223 +#define fICDATAW(RS, RD)
224 +
225 +#define fDCTAGW(RS, RT)
226 +/* tag: RD[23:0], state: RD[30:29] */
227 +#define fDCTAGR(INDEX, DST, DST_REG_NUM) \
228 + do { \
229 + DST = 0; \
230 + } while (0)
231 +#endif
232 +
233 +#else
234 +#define ASSERT_DIRECT_TO_GUEST_UNSET(ENV, EXCP) do { } while (0)
235 +#endif
236 +
237 +#define NUM_TLB_REGS(x) (hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))
238 +
239 +#endif