master
h 349 lines 10.5 KB
Raw
1 /*
2 * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifndef HEXAGON_TRANSLATE_H
19 #define HEXAGON_TRANSLATE_H
20
21 #include "qemu/bitmap.h"
22 #include "qemu/log.h"
23 #include "cpu.h"
24 #include "exec/translator.h"
25 #include "tcg/tcg-op.h"
26 #include "insn.h"
27 #include "internal.h"
28
29 typedef struct DisasContext {
30 DisasContextBase base;
31 Packet pkt;
32 Insn *insn;
33 const HexagonCPUDef *hex_def;
34 uint32_t next_PC;
35 uint32_t mem_idx;
36 uint32_t num_packets;
37 uint32_t num_insns;
38 uint32_t num_hvx_insns;
39 int reg_log[REG_WRITES_MAX];
40 int reg_log_idx;
41 DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
42 DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
43 bool pkt_ends_tb;
44 bool implicit_usr_write;
45 #ifndef CONFIG_USER_ONLY
46 int greg_log[GREG_WRITES_MAX];
47 int greg_log_idx;
48 int sreg_log[SREG_WRITES_MAX];
49 int sreg_log_idx;
50 TCGv_i32 t_sreg_new_value[HEX_SREG_GLB_START];
51 TCGv_i32 greg_new_value[NUM_GREGS];
52 #endif
53 int preg_log[PRED_WRITES_MAX];
54 int preg_log_idx;
55 DECLARE_BITMAP(pregs_written, NUM_PREGS);
56 uint8_t store_width[STORES_MAX];
57 bool s1_store_processed;
58 int future_vregs_idx;
59 int future_vregs_num[VECTOR_TEMPS_MAX];
60 int tmp_vregs_idx;
61 int tmp_vregs_num[VECTOR_TEMPS_MAX];
62 int vreg_log[NUM_VREGS];
63 int vreg_log_idx;
64 DECLARE_BITMAP(vregs_written, NUM_VREGS);
65 DECLARE_BITMAP(insn_vregs_written, NUM_VREGS);
66 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
67 DECLARE_BITMAP(vregs_updated, NUM_VREGS);
68 DECLARE_BITMAP(vregs_select, NUM_VREGS);
69 DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
70 DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
71 DECLARE_BITMAP(insn_vregs_read, NUM_VREGS);
72 int qreg_log[NUM_QREGS];
73 int qreg_log_idx;
74 DECLARE_BITMAP(qregs_written, NUM_QREGS);
75 DECLARE_BITMAP(insn_qregs_written, NUM_QREGS);
76 DECLARE_BITMAP(insn_qregs_read, NUM_QREGS);
77 bool pre_commit;
78 bool need_commit;
79 bool need_next_pc;
80 TCGCond branch_cond;
81 target_ulong branch_dest;
82 bool is_tight_loop;
83 bool short_circuit;
84 bool ieee_fp_extension;
85 bool read_after_write;
86 bool has_hvx_overlap;
87 TCGv new_value[TOTAL_PER_THREAD_REGS];
88 TCGv new_pred_value[NUM_PREGS];
89 TCGv branch_taken;
90 TCGv dczero_addr;
91 bool pcycle_enabled;
92 uint32_t num_cycles;
93 } DisasContext;
94
95 bool is_gather_store_insn(DisasContext *ctx);
96
97 #ifndef CONFIG_USER_ONLY
98 static inline void ctx_log_greg_write(DisasContext *ctx, int rnum)
99 {
100 assert(rnum <= HEX_GREG_G3);
101 ctx->greg_log[ctx->greg_log_idx] = rnum;
102 ctx->greg_log_idx++;
103 }
104
105 static inline void ctx_log_greg_write_pair(DisasContext *ctx, int rnum)
106 {
107 assert(!(rnum % 2));
108 ctx_log_greg_write(ctx, rnum);
109 ctx_log_greg_write(ctx, rnum + 1);
110 }
111
112 static inline void ctx_log_sreg_write(DisasContext *ctx, int rnum)
113 {
114 ctx->sreg_log[ctx->sreg_log_idx] = rnum;
115 ctx->sreg_log_idx++;
116 }
117
118 static inline void ctx_log_sreg_write_pair(DisasContext *ctx, int rnum)
119 {
120 ctx_log_sreg_write(ctx, rnum);
121 ctx_log_sreg_write(ctx, rnum + 1);
122 }
123 #endif
124
125 static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
126 {
127 if (!test_bit(pnum, ctx->pregs_written)) {
128 ctx->preg_log[ctx->preg_log_idx] = pnum;
129 ctx->preg_log_idx++;
130 set_bit(pnum, ctx->pregs_written);
131 }
132 }
133
134 static inline void ctx_log_pred_read(DisasContext *ctx, int pnum)
135 {
136 if (test_bit(pnum, ctx->pregs_written)) {
137 ctx->read_after_write = true;
138 }
139 }
140
141 static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum)
142 {
143 g_assert(test_bit(pnum, ctx->pregs_written));
144 }
145
146 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
147 bool is_predicated)
148 {
149 if (rnum == HEX_REG_P3_0_ALIASED) {
150 for (int i = 0; i < NUM_PREGS; i++) {
151 ctx_log_pred_write(ctx, i);
152 }
153 } else {
154 if (!test_bit(rnum, ctx->regs_written)) {
155 ctx->reg_log[ctx->reg_log_idx] = rnum;
156 ctx->reg_log_idx++;
157 set_bit(rnum, ctx->regs_written);
158 }
159 if (is_predicated) {
160 set_bit(rnum, ctx->predicated_regs);
161 }
162 }
163 }
164
165 static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum,
166 bool is_predicated)
167 {
168 ctx_log_reg_write(ctx, rnum, is_predicated);
169 ctx_log_reg_write(ctx, rnum + 1, is_predicated);
170 }
171
172 static inline void ctx_log_reg_read(DisasContext *ctx, int rnum)
173 {
174 if (test_bit(rnum, ctx->regs_written)) {
175 ctx->read_after_write = true;
176 }
177 }
178
179 static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum)
180 {
181 g_assert(test_bit(rnum, ctx->regs_written));
182 }
183
184 static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
185 {
186 ctx_log_reg_read(ctx, rnum);
187 ctx_log_reg_read(ctx, rnum + 1);
188 }
189
190 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
191 int num, bool alloc_ok);
192 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
193 int num, bool alloc_ok);
194
195 static inline void ctx_start_hvx_insn(DisasContext *ctx)
196 {
197 bitmap_zero(ctx->insn_vregs_written, NUM_VREGS);
198 bitmap_zero(ctx->insn_vregs_read, NUM_VREGS);
199 bitmap_zero(ctx->insn_qregs_written, NUM_QREGS);
200 bitmap_zero(ctx->insn_qregs_read, NUM_QREGS);
201 }
202
203 static inline void ctx_log_vreg_write(DisasContext *ctx,
204 int rnum, VRegWriteType type,
205 bool is_predicated, bool has_helper)
206 {
207 if (has_helper) {
208 set_bit(rnum, ctx->insn_vregs_written);
209 if (test_bit(rnum, ctx->insn_vregs_read)) {
210 ctx->has_hvx_overlap = true;
211 }
212 }
213 set_bit(rnum, ctx->vregs_written);
214 if (type != EXT_TMP) {
215 if (!test_bit(rnum, ctx->vregs_updated)) {
216 ctx->vreg_log[ctx->vreg_log_idx] = rnum;
217 ctx->vreg_log_idx++;
218 set_bit(rnum, ctx->vregs_updated);
219 }
220
221 set_bit(rnum, ctx->vregs_updated);
222 if (is_predicated) {
223 set_bit(rnum, ctx->predicated_future_vregs);
224 }
225 }
226 if (type == EXT_NEW) {
227 set_bit(rnum, ctx->vregs_select);
228 }
229 if (type == EXT_TMP) {
230 set_bit(rnum, ctx->vregs_updated_tmp);
231 if (is_predicated) {
232 set_bit(rnum, ctx->predicated_tmp_vregs);
233 }
234 }
235 }
236
237 static inline void ctx_log_vreg_write_pair(DisasContext *ctx,
238 int rnum, VRegWriteType type,
239 bool is_predicated, bool has_helper)
240 {
241 ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated, has_helper);
242 ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated, has_helper);
243 }
244
245 static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum,
246 bool has_helper)
247 {
248 if (has_helper) {
249 set_bit(rnum, ctx->insn_vregs_read);
250 if (test_bit(rnum, ctx->insn_vregs_written)) {
251 ctx->has_hvx_overlap = true;
252 }
253 }
254 if (test_bit(rnum, ctx->vregs_written)) {
255 ctx->read_after_write = true;
256 }
257 }
258
259 static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum,
260 bool has_helper)
261 {
262 g_assert(is_gather_store_insn(ctx) ||
263 test_bit(rnum, ctx->vregs_updated) ||
264 test_bit(rnum, ctx->vregs_select) ||
265 test_bit(rnum, ctx->vregs_updated_tmp));
266 if (has_helper) {
267 set_bit(rnum, ctx->insn_vregs_read);
268 if (test_bit(rnum, ctx->insn_vregs_written)) {
269 ctx->has_hvx_overlap = true;
270 }
271 }
272 if (is_gather_store_insn(ctx)) {
273 ctx->read_after_write = true;
274 }
275 }
276
277 static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum,
278 bool has_helper)
279 {
280 ctx_log_vreg_read(ctx, rnum ^ 0, has_helper);
281 ctx_log_vreg_read(ctx, rnum ^ 1, has_helper);
282 }
283
284 static inline void ctx_log_qreg_write(DisasContext *ctx,
285 int rnum, bool has_helper)
286 {
287 if (has_helper) {
288 set_bit(rnum, ctx->insn_qregs_written);
289 if (test_bit(rnum, ctx->insn_qregs_read)) {
290 ctx->has_hvx_overlap = true;
291 }
292 }
293 set_bit(rnum, ctx->qregs_written);
294 ctx->qreg_log[ctx->qreg_log_idx] = rnum;
295 ctx->qreg_log_idx++;
296 }
297
298 static inline void ctx_log_qreg_read(DisasContext *ctx,
299 int qnum, bool has_helper)
300 {
301 if (has_helper) {
302 set_bit(qnum, ctx->insn_qregs_read);
303 if (test_bit(qnum, ctx->insn_qregs_written)) {
304 ctx->has_hvx_overlap = true;
305 }
306 }
307 if (test_bit(qnum, ctx->qregs_written)) {
308 ctx->read_after_write = true;
309 }
310 }
311
312 extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
313 extern TCGv hex_pred[NUM_PREGS];
314 extern TCGv hex_slot_cancelled;
315 extern TCGv hex_new_value_usr;
316 extern TCGv hex_next_PC;
317 extern TCGv hex_store_addr[STORES_MAX];
318 extern TCGv_i32 hex_store_width[STORES_MAX];
319 extern TCGv hex_store_val32[STORES_MAX];
320 extern TCGv_i64 hex_store_val64[STORES_MAX];
321 extern TCGv hex_llsc_addr;
322 extern TCGv hex_llsc_val;
323 extern TCGv_i64 hex_llsc_val_i64;
324 extern TCGv hex_vstore_addr[VSTORES_MAX];
325 extern TCGv hex_vstore_size[VSTORES_MAX];
326 extern TCGv hex_vstore_pending[VSTORES_MAX];
327 #ifndef CONFIG_USER_ONLY
328 extern TCGv_i32 hex_greg[NUM_GREGS];
329 extern TCGv_i32 hex_t_sreg[NUM_SREGS];
330 #endif
331
332
333 void hex_gen_exception_end_tb(DisasContext *ctx, int excp);
334
335 void process_store(DisasContext *ctx, int slot_num);
336
337 FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX, 0, 2)
338 FIELD(PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED, 2, 1)
339
340 FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0, 0, 1)
341 FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1, 1, 1)
342 FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_HVX_STORES, 2, 1)
343 FIELD(PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED, 3, 1)
344 FIELD(PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED, 4, 1)
345 FIELD(PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX, 5, 2)
346
347 void gen_framecheck(DisasContext *ctx, TCGv_i32 addr, TCGv_i32 ea);
348
349 #endif