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