master
h 367 lines 14.3 KB
Raw
1 /*
2 * Copyright(c) 2019-2023 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_MMVEC_MACROS_H
19 #define HEXAGON_MMVEC_MACROS_H
20
21 #include "qemu/host-utils.h"
22 #include "arch.h"
23 #include "mmvec/system_ext_mmvec.h"
24 #include "accel/tcg/getpc.h"
25 #include "accel/tcg/probe.h"
26 #include "mmvec/hvx_ieee_fp.h"
27
28 #define fBFLOAT()
29 #define fCVI_VX_NO_TMP_LD()
30
31 #ifndef QEMU_GENERATE
32 #define VdV (*(MMVector *restrict)(VdV_void))
33 #define VsV (*(MMVector *restrict)(VsV_void))
34 #define VuV (*(MMVector *restrict)(VuV_void))
35 #define VvV (*(MMVector *restrict)(VvV_void))
36 #define VwV (*(MMVector *restrict)(VwV_void))
37 #define VxV (*(MMVector *restrict)(VxV_void))
38 #define VyV (*(MMVector *restrict)(VyV_void))
39
40 #define VddV (*(MMVectorPair *restrict)(VddV_void))
41 #define VuuV (*(MMVectorPair *restrict)(VuuV_void))
42 #define VvvV (*(MMVectorPair *restrict)(VvvV_void))
43 #define VxxV (*(MMVectorPair *restrict)(VxxV_void))
44
45 #define QeV (*(MMQReg *restrict)(QeV_void))
46 #define QdV (*(MMQReg *restrict)(QdV_void))
47 #define QsV (*(MMQReg *restrict)(QsV_void))
48 #define QtV (*(MMQReg *restrict)(QtV_void))
49 #define QuV (*(MMQReg *restrict)(QuV_void))
50 #define QvV (*(MMQReg *restrict)(QvV_void))
51 #define QxV (*(MMQReg *restrict)(QxV_void))
52 #endif
53
54 #define LOG_VTCM_BYTE(VA, MASK, VAL, IDX) \
55 do { \
56 env->vtcm_log.data.ub[IDX] = (VAL); \
57 if (MASK) { \
58 set_bit((IDX), env->vtcm_log.mask); \
59 } else { \
60 clear_bit((IDX), env->vtcm_log.mask); \
61 } \
62 env->vtcm_log.va[IDX] = (VA); \
63 } while (0)
64
65 #define fNOTQ(VAL) \
66 ({ \
67 MMQReg _ret; \
68 int _i_; \
69 for (_i_ = 0; _i_ < fVECSIZE() / 64; _i_++) { \
70 _ret.ud[_i_] = ~VAL.ud[_i_]; \
71 } \
72 _ret;\
73 })
74 #define fGETQBITS(REG, WIDTH, MASK, BITNO) \
75 ((MASK) & (REG.w[(BITNO) >> 5] >> ((BITNO) & 0x1f)))
76 #define fGETQBIT(REG, BITNO) fGETQBITS(REG, 1, 1, BITNO)
77 #define fGENMASKW(QREG, IDX) \
78 (((fGETQBIT(QREG, (IDX * 4 + 0)) ? 0xFF : 0x0) << 0) | \
79 ((fGETQBIT(QREG, (IDX * 4 + 1)) ? 0xFF : 0x0) << 8) | \
80 ((fGETQBIT(QREG, (IDX * 4 + 2)) ? 0xFF : 0x0) << 16) | \
81 ((fGETQBIT(QREG, (IDX * 4 + 3)) ? 0xFF : 0x0) << 24))
82 #define fGETNIBBLE(IDX, SRC) (fSXTN(4, 8, (SRC >> (4 * IDX)) & 0xF))
83 #define fGETCRUMB(IDX, SRC) (fSXTN(2, 8, (SRC >> (2 * IDX)) & 0x3))
84 #define fGETCRUMB_SYMMETRIC(IDX, SRC) \
85 ((fGETCRUMB(IDX, SRC) >= 0 ? (2 - fGETCRUMB(IDX, SRC)) \
86 : fGETCRUMB(IDX, SRC)))
87 #define fGENMASKH(QREG, IDX) \
88 (((fGETQBIT(QREG, (IDX * 2 + 0)) ? 0xFF : 0x0) << 0) | \
89 ((fGETQBIT(QREG, (IDX * 2 + 1)) ? 0xFF : 0x0) << 8))
90 #define fGETMASKW(VREG, QREG, IDX) (VREG.w[IDX] & fGENMASKW((QREG), IDX))
91 #define fGETMASKH(VREG, QREG, IDX) (VREG.h[IDX] & fGENMASKH((QREG), IDX))
92 #define fCONDMASK8(QREG, IDX, YESVAL, NOVAL) \
93 (fGETQBIT(QREG, IDX) ? (YESVAL) : (NOVAL))
94 #define fCONDMASK16(QREG, IDX, YESVAL, NOVAL) \
95 ((fGENMASKH(QREG, IDX) & (YESVAL)) | \
96 (fGENMASKH(fNOTQ(QREG), IDX) & (NOVAL)))
97 #define fCONDMASK32(QREG, IDX, YESVAL, NOVAL) \
98 ((fGENMASKW(QREG, IDX) & (YESVAL)) | \
99 (fGENMASKW(fNOTQ(QREG), IDX) & (NOVAL)))
100 #define fSETQBITS(REG, WIDTH, MASK, BITNO, VAL) \
101 do { \
102 uint32_t __TMP = (VAL); \
103 REG.w[(BITNO) >> 5] &= ~((MASK) << ((BITNO) & 0x1f)); \
104 REG.w[(BITNO) >> 5] |= (((__TMP) & (MASK)) << ((BITNO) & 0x1f)); \
105 } while (0)
106 #define fSETQBIT(REG, BITNO, VAL) fSETQBITS(REG, 1, 1, BITNO, VAL)
107 #define fVBYTES() (fVECSIZE())
108 #define fVALIGN(ADDR, LOG2_ALIGNMENT) (ADDR = ADDR & ~(LOG2_ALIGNMENT - 1))
109 #define fVLASTBYTE(ADDR, LOG2_ALIGNMENT) (ADDR = ADDR | (LOG2_ALIGNMENT - 1))
110 #define fVELEM(WIDTH) ((fVECSIZE() * 8) / WIDTH)
111 #define fVECLOGSIZE() (7)
112 #define fVECSIZE() (1 << fVECLOGSIZE())
113 #define fSWAPB(A, B) do { uint8_t tmp = A; A = B; B = tmp; } while (0)
114 #define fV_AL_CHECK(EA, MASK) \
115 if ((EA) & (MASK)) { \
116 warn("aligning misaligned vector. EA=%08x", (EA)); \
117 }
118 #define fSCATTER_INIT(REGION_START, LENGTH, ELEMENT_SIZE) \
119 mem_vector_scatter_init(env)
120 #define fGATHER_INIT(REGION_START, LENGTH, ELEMENT_SIZE) \
121 mem_vector_gather_init(env)
122 #define fSCATTER_FINISH(OP)
123 #define fGATHER_FINISH()
124 #define fLOG_SCATTER_OP(SIZE) \
125 do { \
126 env->vtcm_log.op = true; \
127 env->vtcm_log.op_size = SIZE; \
128 } while (0)
129 #define fVLOG_VTCM_WORD_INCREMENT(EA, OFFSET, INC, IDX, ALIGNMENT, LEN) \
130 do { \
131 int log_byte = 0; \
132 target_ulong va = EA; \
133 target_ulong va_high = EA + LEN; \
134 for (int i0 = 0; i0 < 4; i0++) { \
135 log_byte = (va + i0) <= va_high; \
136 LOG_VTCM_BYTE(va + i0, log_byte, INC. ub[4 * IDX + i0], \
137 4 * IDX + i0); \
138 } \
139 } while (0)
140 #define fVLOG_VTCM_HALFWORD_INCREMENT(EA, OFFSET, INC, IDX, ALIGNMENT, LEN) \
141 do { \
142 int log_byte = 0; \
143 target_ulong va = EA; \
144 target_ulong va_high = EA + LEN; \
145 for (int i0 = 0; i0 < 2; i0++) { \
146 log_byte = (va + i0) <= va_high; \
147 LOG_VTCM_BYTE(va + i0, log_byte, INC.ub[2 * IDX + i0], \
148 2 * IDX + i0); \
149 } \
150 } while (0)
151
152 #define fVLOG_VTCM_HALFWORD_INCREMENT_DV(EA, OFFSET, INC, IDX, IDX2, IDX_H, \
153 ALIGNMENT, LEN) \
154 do { \
155 int log_byte = 0; \
156 target_ulong va = EA; \
157 target_ulong va_high = EA + LEN; \
158 for (int i0 = 0; i0 < 2; i0++) { \
159 log_byte = (va + i0) <= va_high; \
160 LOG_VTCM_BYTE(va + i0, log_byte, INC.ub[2 * IDX + i0], \
161 2 * IDX + i0); \
162 } \
163 } while (0)
164
165 /* NOTE - Will this always be tmp_VRegs[0]; */
166 #define GATHER_FUNCTION(EA, OFFSET, IDX, LEN, ELEMENT_SIZE, BANK_IDX, QVAL) \
167 do { \
168 int i0; \
169 target_ulong va = EA; \
170 target_ulong va_high = EA + LEN; \
171 uintptr_t ra = GETPC(); \
172 int log_byte = 0; \
173 for (i0 = 0; i0 < ELEMENT_SIZE; i0++) { \
174 log_byte = ((va + i0) <= va_high) && QVAL; \
175 uint8_t B; \
176 B = cpu_ldub_data_ra(env, EA + i0, ra); \
177 env->tmp_VRegs[0].ub[ELEMENT_SIZE * IDX + i0] = B; \
178 LOG_VTCM_BYTE(va + i0, log_byte, B, ELEMENT_SIZE * IDX + i0); \
179 } \
180 } while (0)
181 #define fVLOG_VTCM_GATHER_WORD(EA, OFFSET, IDX, LEN) \
182 do { \
183 GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, 1); \
184 } while (0)
185 #define fVLOG_VTCM_GATHER_HALFWORD(EA, OFFSET, IDX, LEN) \
186 do { \
187 GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, 1); \
188 } while (0)
189 #define fVLOG_VTCM_GATHER_HALFWORD_DV(EA, OFFSET, IDX, IDX2, IDX_H, LEN) \
190 do { \
191 GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, (2 * IDX2 + IDX_H), 1); \
192 } while (0)
193 #define fVLOG_VTCM_GATHER_WORDQ(EA, OFFSET, IDX, Q, LEN) \
194 do { \
195 GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, \
196 fGETQBIT(QsV, 4 * IDX + i0)); \
197 } while (0)
198 #define fVLOG_VTCM_GATHER_HALFWORDQ(EA, OFFSET, IDX, Q, LEN) \
199 do { \
200 GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, \
201 fGETQBIT(QsV, 2 * IDX + i0)); \
202 } while (0)
203 #define fVLOG_VTCM_GATHER_HALFWORDQ_DV(EA, OFFSET, IDX, IDX2, IDX_H, Q, LEN) \
204 do { \
205 GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, (2 * IDX2 + IDX_H), \
206 fGETQBIT(QsV, 2 * IDX + i0)); \
207 } while (0)
208 #define SCATTER_OP_WRITE_TO_MEM(TYPE) \
209 do { \
210 ra = GETPC(); \
211 for (int i = 0; i < sizeof(MMVector); i += sizeof(TYPE)) { \
212 if (test_bit(i, env->vtcm_log.mask)) { \
213 TYPE dst = 0; \
214 TYPE inc = 0; \
215 for (int j = 0; j < sizeof(TYPE); j++) { \
216 uint8_t val; \
217 val = cpu_ldub_data_ra(env, env->vtcm_log.va[i + j], ra); \
218 dst |= val << (8 * j); \
219 inc |= env->vtcm_log.data.ub[j + i] << (8 * j); \
220 clear_bit(j + i, env->vtcm_log.mask); \
221 env->vtcm_log.data.ub[j + i] = 0; \
222 } \
223 dst += inc; \
224 for (int j = 0; j < sizeof(TYPE); j++) { \
225 cpu_stb_data_ra(env, env->vtcm_log.va[i + j], \
226 (dst >> (8 * j)) & 0xFF, ra); \
227 } \
228 } \
229 } \
230 } while (0)
231 #define SCATTER_OP_PROBE_MEM(TYPE, MMU_IDX, RETADDR) \
232 do { \
233 for (int i = 0; i < sizeof(MMVector); i += sizeof(TYPE)) { \
234 if (test_bit(i, env->vtcm_log.mask)) { \
235 for (int j = 0; j < sizeof(TYPE); j++) { \
236 probe_read(env, env->vtcm_log.va[i + j], 1, \
237 MMU_IDX, RETADDR); \
238 probe_write(env, env->vtcm_log.va[i + j], 1, \
239 MMU_IDX, RETADDR); \
240 } \
241 } \
242 } \
243 } while (0)
244 #define SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, ELEM_SIZE, BANK_IDX, QVAL, IN) \
245 do { \
246 int i0; \
247 target_ulong va = EA; \
248 target_ulong va_high = EA + LEN; \
249 int log_byte = 0; \
250 for (i0 = 0; i0 < ELEM_SIZE; i0++) { \
251 log_byte = ((va + i0) <= va_high) && QVAL; \
252 LOG_VTCM_BYTE(va + i0, log_byte, IN.ub[ELEM_SIZE * IDX + i0], \
253 ELEM_SIZE * IDX + i0); \
254 } \
255 } while (0)
256 #define fVLOG_VTCM_HALFWORD(EA, OFFSET, IN, IDX, LEN) \
257 do { \
258 SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, 1, IN); \
259 } while (0)
260 #define fVLOG_VTCM_WORD(EA, OFFSET, IN, IDX, LEN) \
261 do { \
262 SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, 1, IN); \
263 } while (0)
264 #define fVLOG_VTCM_HALFWORDQ(EA, OFFSET, IN, IDX, Q, LEN) \
265 do { \
266 SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, \
267 fGETQBIT(QsV, 2 * IDX + i0), IN); \
268 } while (0)
269 #define fVLOG_VTCM_WORDQ(EA, OFFSET, IN, IDX, Q, LEN) \
270 do { \
271 SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, \
272 fGETQBIT(QsV, 4 * IDX + i0), IN); \
273 } while (0)
274 #define fVLOG_VTCM_HALFWORD_DV(EA, OFFSET, IN, IDX, IDX2, IDX_H, LEN) \
275 do { \
276 SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, \
277 (2 * IDX2 + IDX_H), 1, IN); \
278 } while (0)
279 #define fVLOG_VTCM_HALFWORDQ_DV(EA, OFFSET, IN, IDX, Q, IDX2, IDX_H, LEN) \
280 do { \
281 SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, (2 * IDX2 + IDX_H), \
282 fGETQBIT(QsV, 2 * IDX + i0), IN); \
283 } while (0)
284 #define fSTORERELEASE(EA, TYPE) \
285 do { \
286 fV_AL_CHECK(EA, fVECSIZE() - 1); \
287 } while (0)
288 #ifdef QEMU_GENERATE
289 #define fLOADMMV(EA, DST) gen_vreg_load(ctx, DST##_off, EA, true)
290 #endif
291 #ifdef QEMU_GENERATE
292 #define fLOADMMVU(EA, DST) gen_vreg_load(ctx, DST##_off, EA, false)
293 #endif
294 #ifdef QEMU_GENERATE
295 #define fSTOREMMV(EA, SRC) \
296 gen_vreg_store(ctx, EA, SRC##_off, insn->slot, true)
297 #endif
298 #ifdef QEMU_GENERATE
299 #define fSTOREMMVQ(EA, SRC, MASK) \
300 gen_vreg_masked_store(ctx, EA, SRC##_off, MASK##_off, insn->slot, false)
301 #endif
302 #ifdef QEMU_GENERATE
303 #define fSTOREMMVNQ(EA, SRC, MASK) \
304 gen_vreg_masked_store(ctx, EA, SRC##_off, MASK##_off, insn->slot, true)
305 #endif
306 #ifdef QEMU_GENERATE
307 #define fSTOREMMVU(EA, SRC) \
308 gen_vreg_store(ctx, EA, SRC##_off, insn->slot, false)
309 #endif
310 #define fVFOREACH(WIDTH, VAR) for (VAR = 0; VAR < fVELEM(WIDTH); VAR++)
311 #define fVARRAY_ELEMENT_ACCESS(ARRAY, TYPE, INDEX) \
312 ARRAY.v[(INDEX) / (fVECSIZE() / (sizeof(ARRAY.TYPE[0])))].TYPE[(INDEX) % \
313 (fVECSIZE() / (sizeof(ARRAY.TYPE[0])))]
314
315 #define fVSATDW(U, V) fVSATW(((((long long)U) << 32) | fZXTN(32, 64, V)))
316 #define fVASL_SATHI(U, V) fVSATW(((U) << 1) | ((V) >> 31))
317 #define fVUADDSAT(WIDTH, U, V) \
318 fVSATUN(WIDTH, fZXTN(WIDTH, 2 * WIDTH, U) + fZXTN(WIDTH, 2 * WIDTH, V))
319 #define fVSADDSAT(WIDTH, U, V) \
320 fVSATN(WIDTH, fSXTN(WIDTH, 2 * WIDTH, U) + fSXTN(WIDTH, 2 * WIDTH, V))
321 #define fVUSUBSAT(WIDTH, U, V) \
322 fVSATUN(WIDTH, fZXTN(WIDTH, 2 * WIDTH, U) - fZXTN(WIDTH, 2 * WIDTH, V))
323 #define fVSSUBSAT(WIDTH, U, V) \
324 fVSATN(WIDTH, fSXTN(WIDTH, 2 * WIDTH, U) - fSXTN(WIDTH, 2 * WIDTH, V))
325 #define fVAVGU(WIDTH, U, V) \
326 ((fZXTN(WIDTH, 2 * WIDTH, U) + fZXTN(WIDTH, 2 * WIDTH, V)) >> 1)
327 #define fVAVGURND(WIDTH, U, V) \
328 ((fZXTN(WIDTH, 2 * WIDTH, U) + fZXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1)
329 #define fVNAVGU(WIDTH, U, V) \
330 ((fZXTN(WIDTH, 2 * WIDTH, U) - fZXTN(WIDTH, 2 * WIDTH, V)) >> 1)
331 #define fVNAVGURNDSAT(WIDTH, U, V) \
332 fVSATUN(WIDTH, ((fZXTN(WIDTH, 2 * WIDTH, U) - \
333 fZXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1))
334 #define fVAVGS(WIDTH, U, V) \
335 ((fSXTN(WIDTH, 2 * WIDTH, U) + fSXTN(WIDTH, 2 * WIDTH, V)) >> 1)
336 #define fVAVGSRND(WIDTH, U, V) \
337 ((fSXTN(WIDTH, 2 * WIDTH, U) + fSXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1)
338 #define fVNAVGS(WIDTH, U, V) \
339 ((fSXTN(WIDTH, 2 * WIDTH, U) - fSXTN(WIDTH, 2 * WIDTH, V)) >> 1)
340 #define fVNAVGSRND(WIDTH, U, V) \
341 ((fSXTN(WIDTH, 2 * WIDTH, U) - fSXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1)
342 #define fVNAVGSRNDSAT(WIDTH, U, V) \
343 fVSATN(WIDTH, ((fSXTN(WIDTH, 2 * WIDTH, U) - \
344 fSXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1))
345 #define fVNOROUND(VAL, SHAMT) VAL
346 #define fVNOSAT(VAL) VAL
347 #define fVROUND(VAL, SHAMT) \
348 ((VAL) + (((SHAMT) > 0) ? (1LL << ((SHAMT) - 1)) : 0))
349 #define fCARRY_FROM_ADD32(A, B, C) \
350 (((fZXTN(32, 64, A) + fZXTN(32, 64, B) + C) >> 32) & 1)
351 #define fUARCH_NOTE_PUMP_4X()
352 #define fUARCH_NOTE_PUMP_2X()
353
354 #define IV1DEAD()
355
356 #define fGET10BIT(COE, VAL, POS) \
357 do { \
358 COE = (sextract32(VAL, 24 + 2 * POS, 2) << 8) | \
359 extract32(VAL, POS * 8, 8); \
360 } while (0) \
361 ;
362
363 #define fCMPGT_SF(A, B) cmpgt_sf(A, B, &env->hvx_fp_status)
364 #define fCMPGT_HF(A, B) cmpgt_hf(A, B, &env->hvx_fp_status)
365 #define fCMPGT_BF(A, B) fCMPGT_SF((uint32_t)(A) << 16, (uint32_t)(B) << 16)
366
367 #endif