master
c 897 lines 28.4 KB
Raw
1 /*
2 * Octeon-specific instructions translation routines
3 *
4 * Copyright (c) 2022 Pavel Dovgalyuk
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "translate.h"
11 #include "tcg/tcg-op-gvec.h"
12
13 /* Include the auto-generated decoder. */
14 #include "decode-octeon.c.inc"
15
16 #define OCTEON_CRYPTO_OFFSET(FIELD) \
17 offsetof(CPUMIPSState, octeon_crypto.FIELD)
18
19 #define CP2_MF_I64(NAME, FIELD) \
20 TRANS(NAME, trans_octeon_cp2_mf_i64, OCTEON_CRYPTO_OFFSET(FIELD))
21 #define CP2_MF_S32(NAME, FIELD) \
22 TRANS(NAME, trans_octeon_cp2_mf_s32, OCTEON_CRYPTO_OFFSET(FIELD))
23 #define CP2_MF_U16(NAME, FIELD) \
24 TRANS(NAME, trans_octeon_cp2_mf_u16, OCTEON_CRYPTO_OFFSET(FIELD))
25 #define CP2_MF_U8(NAME, FIELD) \
26 TRANS(NAME, trans_octeon_cp2_mf_u8, OCTEON_CRYPTO_OFFSET(FIELD))
27 #define CP2_MF_HSH_PAIR(NAME, FIELD, INDEX) \
28 TRANS(NAME, trans_octeon_cp2_mf_hsh_pair, \
29 OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX)]), \
30 OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX) + 1]))
31 #define CP2_MF_REFLECT(NAME, FIELD) \
32 TRANS(NAME, trans_octeon_cp2_mf_reflect, OCTEON_CRYPTO_OFFSET(FIELD))
33 #define CP2_MF_HELPER(NAME, SUFFIX) \
34 TRANS(NAME, trans_octeon_cp2_mf_helper, \
35 gen_helper_octeon_cp2_mf_ ## SUFFIX)
36 #define CP2_MT_I64(NAME, FIELD) \
37 TRANS(NAME, trans_octeon_cp2_mt_i64, OCTEON_CRYPTO_OFFSET(FIELD))
38 #define CP2_MT_U32(NAME, FIELD) \
39 TRANS(NAME, trans_octeon_cp2_mt_u32, OCTEON_CRYPTO_OFFSET(FIELD))
40 #define CP2_MT_U16(NAME, FIELD) \
41 TRANS(NAME, trans_octeon_cp2_mt_u16, OCTEON_CRYPTO_OFFSET(FIELD))
42 #define CP2_MT_U8_MASKED(NAME, FIELD, MASK) \
43 TRANS(NAME, trans_octeon_cp2_mt_u8_masked, \
44 OCTEON_CRYPTO_OFFSET(FIELD), MASK)
45 #define CP2_MT_HSH_PAIR(NAME, FIELD, INDEX) \
46 TRANS(NAME, trans_octeon_cp2_mt_hsh_pair, \
47 OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX)]), \
48 OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX) + 1]))
49 #define CP2_MT_REFLECT(NAME, FIELD) \
50 TRANS(NAME, trans_octeon_cp2_mt_reflect, OCTEON_CRYPTO_OFFSET(FIELD))
51 #define CP2_MT_HELPER(NAME, SUFFIX) \
52 TRANS(NAME, trans_octeon_cp2_mt_helper, \
53 gen_helper_octeon_cp2_mt_ ## SUFFIX)
54 #define CP2_MT_HELPER_ENV(NAME, SUFFIX) \
55 TRANS(NAME, trans_octeon_cp2_mt_helper_env, \
56 gen_helper_octeon_cp2_mt_ ## SUFFIX)
57 #define CP2_MT_XOR_I64(NAME, FIELD) \
58 TRANS(NAME, trans_octeon_cp2_mt_xor_i64, OCTEON_CRYPTO_OFFSET(FIELD))
59
60 #define OCTEON_LO32_OFFSET (HOST_BIG_ENDIAN ? 4 : 0)
61
62 static bool trans_CP2_Undef(DisasContext *ctx, arg_CP2_Undef *a)
63 {
64 generate_exception_err(ctx, EXCP_CpU, 2);
65 return true;
66 }
67
68 static bool trans_octeon_cp2_mf_i64(DisasContext *ctx, arg_cp2 *a, int offset)
69 {
70 TCGv_i64 value = tcg_temp_new_i64();
71
72 tcg_gen_ld_i64(value, tcg_env, offset);
73 gen_store_gpr(value, a->rt);
74 return true;
75 }
76
77 static bool trans_octeon_cp2_mf_s32(DisasContext *ctx, arg_cp2 *a, int offset)
78 {
79 TCGv_i64 value = tcg_temp_new_i64();
80
81 tcg_gen_ld32s_i64(value, tcg_env, offset);
82 gen_store_gpr(value, a->rt);
83 return true;
84 }
85
86 static bool trans_octeon_cp2_mf_u16(DisasContext *ctx, arg_cp2 *a, int offset)
87 {
88 TCGv_i64 value = tcg_temp_new_i64();
89
90 tcg_gen_ld16u_i64(value, tcg_env, offset);
91 gen_store_gpr(value, a->rt);
92 return true;
93 }
94
95 static bool trans_octeon_cp2_mf_u8(DisasContext *ctx, arg_cp2 *a, int offset)
96 {
97 TCGv_i64 value = tcg_temp_new_i64();
98
99 tcg_gen_ld8u_i64(value, tcg_env, offset);
100 gen_store_gpr(value, a->rt);
101 return true;
102 }
103
104 static bool trans_octeon_cp2_mf_hsh_pair(DisasContext *ctx, arg_cp2 *a,
105 int hi_offset, int lo_offset)
106 {
107 TCGv_i64 hi = tcg_temp_new_i64();
108 TCGv_i64 lo = tcg_temp_new_i64();
109
110 tcg_gen_ld_i64(hi, tcg_env, hi_offset);
111 tcg_gen_ld_i64(lo, tcg_env, lo_offset);
112 tcg_gen_concat32_i64(lo, lo, hi);
113 gen_store_gpr(lo, a->rt);
114 return true;
115 }
116
117 static bool trans_octeon_cp2_mf_reflect(DisasContext *ctx, arg_cp2 *a,
118 int offset)
119 {
120 TCGv_i64 value = tcg_temp_new_i64();
121
122 tcg_gen_ld_i64(value, tcg_env, offset);
123 tcg_gen_revbit64_i64(value, value);
124 gen_store_gpr(value, a->rt);
125 return true;
126 }
127
128 static bool trans_octeon_cp2_mf_helper(DisasContext *ctx, arg_cp2 *a,
129 void (*gen_helper)(TCGv_i64, TCGv_env))
130 {
131 TCGv_i64 value = tcg_temp_new_i64();
132
133 gen_helper(value, tcg_env);
134 gen_store_gpr(value, a->rt);
135 return true;
136 }
137
138 static bool trans_octeon_cp2_mt_i64(DisasContext *ctx, arg_cp2 *a, int offset)
139 {
140 TCGv_i64 value = tcg_temp_new_i64();
141
142 gen_load_gpr(value, a->rt);
143 tcg_gen_st_i64(value, tcg_env, offset);
144 return true;
145 }
146
147 static bool trans_octeon_cp2_mt_u32(DisasContext *ctx, arg_cp2 *a, int offset)
148 {
149 TCGv_i64 value = tcg_temp_new_i64();
150
151 gen_load_gpr(value, a->rt);
152 tcg_gen_st32_i64(value, tcg_env, offset);
153 return true;
154 }
155
156 static bool trans_octeon_cp2_mt_u16(DisasContext *ctx, arg_cp2 *a, int offset)
157 {
158 TCGv_i64 value = tcg_temp_new_i64();
159
160 gen_load_gpr(value, a->rt);
161 tcg_gen_st16_i64(value, tcg_env, offset);
162 return true;
163 }
164
165 static bool trans_octeon_cp2_mt_u8_masked(DisasContext *ctx, arg_cp2 *a,
166 int offset, uint8_t mask)
167 {
168 TCGv_i64 value = tcg_temp_new_i64();
169
170 gen_load_gpr(value, a->rt);
171 tcg_gen_andi_i64(value, value, mask);
172 tcg_gen_st8_i64(value, tcg_env, offset);
173 return true;
174 }
175
176 static bool trans_octeon_cp2_mt_hsh_pair(DisasContext *ctx, arg_cp2 *a,
177 int hi_offset, int lo_offset)
178 {
179 TCGv_i64 value = tcg_temp_new_i64();
180
181 gen_load_gpr(value, a->rt);
182 tcg_gen_st32_i64(value, tcg_env, lo_offset + OCTEON_LO32_OFFSET);
183 tcg_gen_shri_i64(value, value, 32);
184 tcg_gen_st32_i64(value, tcg_env, hi_offset + OCTEON_LO32_OFFSET);
185 return true;
186 }
187
188 static bool trans_octeon_cp2_mt_xor_i64(DisasContext *ctx, arg_cp2 *a,
189 int offset)
190 {
191 TCGv_i64 value = tcg_temp_new_i64();
192 TCGv_i64 old = tcg_temp_new_i64();
193
194 gen_load_gpr(value, a->rt);
195 tcg_gen_ld_i64(old, tcg_env, offset);
196 tcg_gen_xor_i64(old, old, value);
197 tcg_gen_st_i64(old, tcg_env, offset);
198 return true;
199 }
200
201 static bool trans_octeon_cp2_mt_reflect(DisasContext *ctx, arg_cp2 *a,
202 int offset)
203 {
204 TCGv_i64 value = tcg_temp_new_i64();
205
206 gen_load_gpr(value, a->rt);
207 tcg_gen_revbit64_i64(value, value);
208 tcg_gen_st_i64(value, tcg_env, offset);
209 return true;
210 }
211
212 static bool trans_octeon_cp2_mt_helper(DisasContext *ctx, arg_cp2 *a,
213 void (*gen_helper)(TCGv_env, TCGv_i64))
214 {
215 TCGv_i64 value = tcg_temp_new_i64();
216
217 gen_load_gpr(value, a->rt);
218 gen_helper(tcg_env, value);
219 return true;
220 }
221
222 static bool trans_octeon_cp2_mt_helper_env(DisasContext *ctx, arg_cp2 *a,
223 void (*gen_helper)(TCGv_env))
224 {
225 gen_helper(tcg_env);
226 return true;
227 }
228
229 static void gen_helper_octeon_cp2_mt_gfm_xor0_reflect(TCGv_env t_env,
230 TCGv_i64 value)
231 {
232 TCGv_i64 resinp = tcg_temp_new_i64();
233
234 tcg_gen_revbit64_i64(value, value);
235 tcg_gen_ld_i64(resinp, t_env, OCTEON_CRYPTO_OFFSET(gfm_resinp[0]));
236 tcg_gen_xor_i64(resinp, resinp, value);
237 tcg_gen_st_i64(resinp, t_env, OCTEON_CRYPTO_OFFSET(gfm_resinp[0]));
238 }
239
240 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT0, hsh_dat, 0);
241 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT1, hsh_dat, 1);
242 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT2, hsh_dat, 2);
243 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT3, hsh_dat, 3);
244 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT4, hsh_dat, 4);
245 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT5, hsh_dat, 5);
246 CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT6, hsh_dat, 6);
247 CP2_MF_HSH_PAIR(CVM_MF_HSH_IV0, hsh_iv, 0);
248 CP2_MF_HSH_PAIR(CVM_MF_HSH_IV1, hsh_iv, 1);
249 CP2_MF_HSH_PAIR(CVM_MF_HSH_IV2, hsh_iv, 2);
250 CP2_MF_HSH_PAIR(CVM_MF_HSH_IV3, hsh_iv, 3);
251 CP2_MF_I64(CVM_MF_3DES_KEY0, des3_key[0]);
252 CP2_MF_I64(CVM_MF_3DES_KEY1, des3_key[1]);
253 CP2_MF_I64(CVM_MF_3DES_KEY2, des3_key[2]);
254 CP2_MF_I64(CVM_MF_3DES_IV, des3_iv);
255 CP2_MF_I64(CVM_MF_3DES_RESULT, des3_result);
256 CP2_MF_I64(CVM_MF_KAS_RESULT, des3_result);
257 CP2_MF_I64(CVM_MF_AES_RESINP0, aes_resinp[0]);
258 CP2_MF_I64(CVM_MF_AES_RESINP1, aes_resinp[1]);
259 CP2_MF_I64(CVM_MF_AES_IV0, aes_iv[0]);
260 CP2_MF_I64(CVM_MF_AES_IV1, aes_iv[1]);
261 CP2_MF_I64(CVM_MF_AES_KEY0, aes_key[0]);
262 CP2_MF_I64(CVM_MF_AES_KEY1, aes_key[1]);
263 CP2_MF_I64(CVM_MF_AES_KEY2, aes_key[2]);
264 CP2_MF_I64(CVM_MF_AES_KEY3, aes_key[3]);
265 CP2_MF_U8(CVM_MF_AES_KEYLENGTH, aes_keylen);
266 CP2_MF_I64(CVM_MF_AES_INP0, aes_resinp[0]);
267 CP2_MF_S32(CVM_MF_CRC_POLYNOMIAL, crc_poly);
268 CP2_MF_S32(CVM_MF_CRC_IV, crc_iv);
269 CP2_MF_U8(CVM_MF_CRC_LEN, crc_len);
270 CP2_MF_I64(CVM_MF_GFM_MUL0, gfm_mul[0]);
271 CP2_MF_I64(CVM_MF_GFM_MUL1, gfm_mul[1]);
272 CP2_MF_I64(CVM_MF_GFM_RESINP0, gfm_resinp[0]);
273 CP2_MF_I64(CVM_MF_GFM_RESINP1, gfm_resinp[1]);
274 CP2_MF_U16(CVM_MF_GFM_POLY, gfm_poly);
275 CP2_MF_I64(CVM_MF_CHORD, chord);
276 CP2_MF_I64(CVM_MF_LLM_DATA0, llm_data[0]);
277 CP2_MF_I64(CVM_MF_LLM_DATA1, llm_data[1]);
278
279 CP2_MF_HELPER(CVM_MF_CRC_IV_REFLECT, crc_iv_reflect);
280 CP2_MF_I64(CVM_MF_SHA3_DAT24, sha3_dat24);
281 CP2_MF_REFLECT(CVM_MF_GFM_MUL_REFLECT0, gfm_mul[0])
282 CP2_MF_REFLECT(CVM_MF_GFM_MUL_REFLECT1, gfm_mul[1])
283 CP2_MF_REFLECT(CVM_MF_GFM_RESINP_REFLECT0, gfm_resinp[0])
284 CP2_MF_REFLECT(CVM_MF_GFM_RESINP_REFLECT1, gfm_resinp[1])
285 CP2_MF_I64(CVM_MF_HSH_DATW0, hsh_dat[0]);
286 CP2_MF_I64(CVM_MF_HSH_DATW1, hsh_dat[1]);
287 CP2_MF_I64(CVM_MF_HSH_DATW2, hsh_dat[2]);
288 CP2_MF_I64(CVM_MF_HSH_DATW3, hsh_dat[3]);
289 CP2_MF_I64(CVM_MF_HSH_DATW4, hsh_dat[4]);
290 CP2_MF_I64(CVM_MF_HSH_DATW5, hsh_dat[5]);
291 CP2_MF_I64(CVM_MF_HSH_DATW6, hsh_dat[6]);
292 CP2_MF_I64(CVM_MF_HSH_DATW7, hsh_dat[7]);
293 CP2_MF_I64(CVM_MF_HSH_DATW8, hsh_dat[8]);
294 CP2_MF_I64(CVM_MF_HSH_DATW9, hsh_dat[9]);
295 CP2_MF_I64(CVM_MF_HSH_DATW10, hsh_dat[10]);
296 CP2_MF_I64(CVM_MF_HSH_DATW11, hsh_dat[11]);
297 CP2_MF_I64(CVM_MF_HSH_DATW12, hsh_dat[12]);
298 CP2_MF_I64(CVM_MF_HSH_DATW13, hsh_dat[13]);
299 CP2_MF_I64(CVM_MF_HSH_DATW14, hsh_dat[14]);
300 CP2_MF_I64(CVM_MF_HSH_DATW15, hsh_dat[15]);
301 CP2_MF_I64(CVM_MF_HSH_IVW0, hsh_iv[0]);
302 CP2_MF_I64(CVM_MF_HSH_IVW1, hsh_iv[1]);
303 CP2_MF_I64(CVM_MF_HSH_IVW2, hsh_iv[2]);
304 CP2_MF_I64(CVM_MF_HSH_IVW3, hsh_iv[3]);
305 CP2_MF_I64(CVM_MF_HSH_IVW4, hsh_iv[4]);
306 CP2_MF_I64(CVM_MF_HSH_IVW5, hsh_iv[5]);
307 CP2_MF_I64(CVM_MF_HSH_IVW6, hsh_iv[6]);
308 CP2_MF_I64(CVM_MF_HSH_IVW7, hsh_iv[7]);
309
310 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT0, hsh_dat, 0);
311 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT1, hsh_dat, 1);
312 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT2, hsh_dat, 2);
313 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT3, hsh_dat, 3);
314 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT4, hsh_dat, 4);
315 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT5, hsh_dat, 5);
316 CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT6, hsh_dat, 6);
317 CP2_MT_HSH_PAIR(CVM_MT_HSH_IV0, hsh_iv, 0);
318 CP2_MT_HSH_PAIR(CVM_MT_HSH_IV1, hsh_iv, 1);
319 CP2_MT_HSH_PAIR(CVM_MT_HSH_IV2, hsh_iv, 2);
320 CP2_MT_HSH_PAIR(CVM_MT_HSH_IV3, hsh_iv, 3);
321 CP2_MT_REFLECT(CVM_MT_GFM_MUL_REFLECT0, gfm_mul[0]);
322 CP2_MT_REFLECT(CVM_MT_GFM_MUL_REFLECT1, gfm_mul[1]);
323 CP2_MT_HELPER(CVM_MT_GFM_XOR0_REFLECT, gfm_xor0_reflect);
324 CP2_MT_I64(CVM_MT_3DES_KEY0, des3_key[0]);
325 CP2_MT_I64(CVM_MT_3DES_KEY1, des3_key[1]);
326 CP2_MT_I64(CVM_MT_3DES_KEY2, des3_key[2]);
327 CP2_MT_I64(CVM_MT_3DES_IV, des3_iv);
328 CP2_MT_I64(CVM_MT_3DES_RESULT, des3_result);
329 CP2_MT_I64(CVM_MT_AES_RESINP0, aes_resinp[0]);
330 CP2_MT_I64(CVM_MT_AES_RESINP1, aes_resinp[1]);
331 CP2_MT_I64(CVM_MT_AES_IV0, aes_iv[0]);
332 CP2_MT_I64(CVM_MT_AES_IV1, aes_iv[1]);
333 CP2_MT_I64(CVM_MT_AES_KEY0, aes_key[0]);
334 CP2_MT_I64(CVM_MT_AES_KEY1, aes_key[1]);
335 CP2_MT_I64(CVM_MT_AES_KEY2, aes_key[2]);
336 CP2_MT_I64(CVM_MT_AES_KEY3, aes_key[3]);
337 CP2_MT_I64(CVM_MT_AES_ENC_CBC0, aes_resinp[0]);
338 CP2_MT_I64(CVM_MT_AES_ENC0, aes_resinp[0]);
339 CP2_MT_I64(CVM_MT_AES_DEC_CBC0, aes_resinp[0]);
340 CP2_MT_I64(CVM_MT_AES_DEC0, aes_resinp[0]);
341 CP2_MT_U8_MASKED(CVM_MT_AES_KEYLENGTH, aes_keylen, 3);
342 CP2_MT_U32(CVM_MT_CRC_IV, crc_iv);
343 CP2_MT_I64(CVM_MT_GFM_MUL0, gfm_mul[0]);
344 CP2_MT_I64(CVM_MT_GFM_MUL1, gfm_mul[1]);
345 CP2_MT_I64(CVM_MT_GFM_RESINP0, gfm_resinp[0]);
346 CP2_MT_I64(CVM_MT_GFM_RESINP1, gfm_resinp[1]);
347 CP2_MT_XOR_I64(CVM_MT_GFM_XOR0, gfm_resinp[0]);
348 CP2_MT_U16(CVM_MT_GFM_POLY, gfm_poly);
349 CP2_MT_I64(CVM_MT_LLM_DATA0, llm_data[0]);
350 CP2_MT_I64(CVM_MT_LLM_DATA1, llm_data[1]);
351 CP2_MT_U8_MASKED(CVM_MT_CRC_LEN, crc_len, 0xf);
352 CP2_MT_U32(CVM_MT_CRC_POLYNOMIAL, crc_poly);
353
354 CP2_MT_HELPER(CVM_MT_CRC_POLYNOMIAL_REFLECT, crc_write_polynomial_reflect);
355
356 CP2_MT_HELPER(CVM_MT_CRC_IV_REFLECT, crc_write_iv_reflect);
357 CP2_MT_HELPER(CVM_MT_CRC_BYTE, crc_write_byte);
358 CP2_MT_HELPER(CVM_MT_CRC_HALF, crc_write_half);
359 CP2_MT_HELPER(CVM_MT_CRC_WORD, crc_write_word);
360 CP2_MT_HELPER(CVM_MT_CRC_BYTE_REFLECT, crc_write_byte_reflect);
361 CP2_MT_HELPER(CVM_MT_CRC_HALF_REFLECT, crc_write_half_reflect);
362 CP2_MT_HELPER(CVM_MT_CRC_WORD_REFLECT, crc_write_word_reflect);
363 CP2_MT_HELPER(CVM_MT_CRC_DWORD, crc_write_dword);
364 CP2_MT_HELPER(CVM_MT_CRC_VAR, crc_write_var);
365 CP2_MT_HELPER(CVM_MT_CRC_DWORD_REFLECT, crc_write_dword_reflect);
366 CP2_MT_HELPER(CVM_MT_CRC_VAR_REFLECT, crc_write_var_reflect);
367 CP2_MT_HELPER(CVM_MT_GFM_XORMUL1_REFLECT, gfm_xormul1_reflect);
368 CP2_MT_HELPER(CVM_MT_GFM_XORMUL1, gfm_xormul1);
369 CP2_MT_I64(CVM_MT_SHA3_DAT24, sha3_dat24);
370 CP2_MT_I64(CVM_MT_SHA3_DAT15, hsh_dat[15]);
371 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT0, sha3_dat[0]);
372 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT1, sha3_dat[1]);
373 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT2, sha3_dat[2]);
374 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT3, sha3_dat[3]);
375 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT4, sha3_dat[4]);
376 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT5, sha3_dat[5]);
377 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT6, sha3_dat[6]);
378 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT7, sha3_dat[7]);
379 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT8, sha3_dat[8]);
380 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT9, sha3_dat[9]);
381 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT10, sha3_dat[10]);
382 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT11, sha3_dat[11]);
383 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT12, sha3_dat[12]);
384 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT13, sha3_dat[13]);
385 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT14, sha3_dat[14]);
386 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT15, sha3_dat[15]);
387 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT16, sha3_dat[16]);
388 CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT17, sha3_dat[17]);
389 CP2_MT_HELPER_ENV(CVM_MT_SHA3_STARTOP, sha3_startop);
390 CP2_MT_HELPER(CVM_MT_ZUC_START, zuc_start);
391 CP2_MT_HELPER(CVM_MT_ZUC_MORE, zuc_more);
392 CP2_MT_HELPER(CVM_MT_SNOW3G_START, snow3g_start);
393 CP2_MT_HELPER(CVM_MT_SNOW3G_MORE, snow3g_more);
394 CP2_MT_HELPER(CVM_MT_AES_ENC_CBC1, aes_enc_cbc1);
395 CP2_MT_HELPER(CVM_MT_AES_ENC1, aes_enc1);
396 CP2_MT_HELPER(CVM_MT_AES_DEC_CBC1, aes_dec_cbc1);
397 CP2_MT_HELPER(CVM_MT_AES_DEC1, aes_dec1);
398 CP2_MT_HELPER(CVM_MT_SMS4_ENC_CBC1, sms4_enc_cbc1);
399 CP2_MT_HELPER(CVM_MT_SMS4_ENC1, sms4_enc1);
400 CP2_MT_HELPER(CVM_MT_SMS4_DEC_CBC1, sms4_dec_cbc1);
401 CP2_MT_HELPER(CVM_MT_SMS4_DEC1, sms4_dec1);
402 CP2_MT_HELPER(CVM_MT_3DES_ENC_CBC, des3_enc_cbc);
403 CP2_MT_HELPER(CVM_MT_KAS_ENC_CBC, kas_enc_cbc);
404 CP2_MT_HELPER(CVM_MT_3DES_ENC, des3_enc);
405 CP2_MT_HELPER(CVM_MT_KAS_ENC, kas_enc);
406 CP2_MT_HELPER(CVM_MT_3DES_DEC_CBC, des3_dec_cbc);
407 CP2_MT_HELPER(CVM_MT_3DES_DEC, des3_dec);
408 CP2_MT_HELPER(CVM_MT_CAMELLIA_FL, camellia_fl);
409 CP2_MT_HELPER(CVM_MT_CAMELLIA_FLINV, camellia_flinv);
410 CP2_MT_HELPER(CVM_MT_CAMELLIA_ROUND, camellia_round);
411 CP2_MT_HELPER(CVM_MT_HSH_STARTSHA1_COMPAT, hsh_startsha1_compat);
412 CP2_MT_I64(CVM_MT_HSH_DATW0, hsh_dat[0]);
413 CP2_MT_I64(CVM_MT_HSH_DATW1, hsh_dat[1]);
414 CP2_MT_I64(CVM_MT_HSH_DATW2, hsh_dat[2]);
415 CP2_MT_I64(CVM_MT_HSH_DATW3, hsh_dat[3]);
416 CP2_MT_I64(CVM_MT_HSH_DATW4, hsh_dat[4]);
417 CP2_MT_I64(CVM_MT_HSH_DATW5, hsh_dat[5]);
418 CP2_MT_I64(CVM_MT_HSH_DATW6, hsh_dat[6]);
419 CP2_MT_I64(CVM_MT_HSH_DATW7, hsh_dat[7]);
420 CP2_MT_I64(CVM_MT_HSH_DATW8, hsh_dat[8]);
421 CP2_MT_I64(CVM_MT_HSH_DATW9, hsh_dat[9]);
422 CP2_MT_I64(CVM_MT_HSH_DATW10, hsh_dat[10]);
423 CP2_MT_I64(CVM_MT_HSH_DATW11, hsh_dat[11]);
424 CP2_MT_I64(CVM_MT_HSH_DATW12, hsh_dat[12]);
425 CP2_MT_I64(CVM_MT_HSH_DATW13, hsh_dat[13]);
426 CP2_MT_I64(CVM_MT_HSH_DATW14, hsh_dat[14]);
427 CP2_MT_I64(CVM_MT_HSH_DATW15, hsh_dat[15]);
428 CP2_MT_I64(CVM_MT_HSH_IVW0, hsh_iv[0]);
429 CP2_MT_I64(CVM_MT_HSH_IVW1, hsh_iv[1]);
430 CP2_MT_I64(CVM_MT_HSH_IVW2, hsh_iv[2]);
431 CP2_MT_I64(CVM_MT_HSH_IVW3, hsh_iv[3]);
432 CP2_MT_I64(CVM_MT_HSH_IVW4, hsh_iv[4]);
433 CP2_MT_I64(CVM_MT_HSH_IVW5, hsh_iv[5]);
434 CP2_MT_I64(CVM_MT_HSH_IVW6, hsh_iv[6]);
435 CP2_MT_I64(CVM_MT_HSH_IVW7, hsh_iv[7]);
436 CP2_MT_HELPER(CVM_MT_HSH_STARTMD5, hsh_startmd5);
437 CP2_MT_HELPER(CVM_MT_HSH_STARTSHA256, hsh_startsha256);
438 CP2_MT_HELPER(CVM_MT_HSH_STARTSHA, hsh_startsha);
439 CP2_MT_HELPER(CVM_MT_HSH_STARTSHA512, hsh_startsha512);
440 CP2_MT_HELPER(CVM_MT_LLM_READ_ADDR0, llm_read_addr0);
441 CP2_MT_HELPER(CVM_MT_LLM_WRITE_ADDR0, llm_write_addr0);
442 CP2_MT_HELPER(CVM_MT_LLM_READ64_ADDR0, llm_read64_addr0);
443 CP2_MT_HELPER(CVM_MT_LLM_WRITE64_ADDR0, llm_write64_addr0);
444 CP2_MT_HELPER(CVM_MT_LLM_READ_ADDR1, llm_read_addr1);
445 CP2_MT_HELPER(CVM_MT_LLM_WRITE_ADDR1, llm_write_addr1);
446 CP2_MT_HELPER(CVM_MT_LLM_READ64_ADDR1, llm_read64_addr1);
447 CP2_MT_HELPER(CVM_MT_LLM_WRITE64_ADDR1, llm_write64_addr1);
448
449 static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
450 {
451 TCGv_i64 p;
452
453 if (ctx->hflags & MIPS_HFLAG_BMASK) {
454 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%" VADDR_PRIx "\n",
455 ctx->base.pc_next);
456 generate_exception_end(ctx, EXCP_RI);
457 return true;
458 }
459
460 /* Load needed operands */
461 TCGv_i64 t0 = tcg_temp_new_i64();
462 gen_load_gpr(t0, a->rs);
463
464 p = tcg_constant_i64(1ULL << a->p);
465 if (a->set) {
466 tcg_gen_and_i64(bcond, p, t0);
467 } else {
468 tcg_gen_andc_i64(bcond, p, t0);
469 }
470
471 ctx->hflags |= MIPS_HFLAG_BC;
472 ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4;
473 ctx->hflags |= MIPS_HFLAG_BDS32;
474 return true;
475 }
476
477 static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a)
478 {
479 TCGv_i64 t0, t1;
480
481 t0 = tcg_temp_new_i64();
482 t1 = tcg_temp_new_i64();
483 gen_load_gpr(t0, a->rs);
484 gen_load_gpr(t1, a->rt);
485
486 tcg_gen_add_i64(t0, t0, t1);
487 tcg_gen_andi_i64(t0, t0, 0xff);
488 gen_store_gpr(t0, a->rd);
489 return true;
490 }
491
492 static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a)
493 {
494 TCGv_i64 t0, t1;
495
496 t0 = tcg_temp_new_i64();
497 t1 = tcg_temp_new_i64();
498 gen_load_gpr(t0, a->rs);
499 gen_load_gpr(t1, a->rt);
500
501 tcg_gen_mul_i64(t0, t0, t1);
502 gen_store_gpr(t0, a->rd);
503 return true;
504 }
505
506 static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a)
507 {
508 TCGv_i64 t0;
509
510 t0 = tcg_temp_new_i64();
511 gen_load_gpr(t0, a->rs);
512 tcg_gen_sextract_i64(t0, t0, a->p, a->lenm1 + 1);
513 gen_store_gpr(t0, a->rt);
514 return true;
515 }
516
517 static bool trans_CINS(DisasContext *ctx, arg_CINS *a)
518 {
519 TCGv_i64 t0;
520
521 t0 = tcg_temp_new_i64();
522 gen_load_gpr(t0, a->rs);
523 tcg_gen_deposit_z_i64(t0, t0, a->p, a->lenm1 + 1);
524 gen_store_gpr(t0, a->rt);
525 return true;
526 }
527
528 static bool trans_POP(DisasContext *ctx, arg_POP *a)
529 {
530 TCGv_i64 t0;
531
532 t0 = tcg_temp_new_i64();
533 gen_load_gpr(t0, a->rs);
534 if (!a->dw) {
535 tcg_gen_andi_i64(t0, t0, 0xffffffff);
536 }
537 tcg_gen_ctpop_i64(t0, t0);
538 gen_store_gpr(t0, a->rd);
539 return true;
540 }
541
542 static bool do_seq_sne(DisasContext *ctx, const arg_decode_ext_octeon1 *a,
543 TCGCond cond)
544 {
545 TCGv_i64 t0, t1;
546
547 t0 = tcg_temp_new_i64();
548 t1 = tcg_temp_new_i64();
549
550 gen_load_gpr(t0, a->rs);
551 gen_load_gpr(t1, a->rt);
552
553 tcg_gen_setcond_i64(cond, t0, t1, t0);
554 gen_store_gpr(t0, a->rd);
555 return true;
556 }
557
558 static bool trans_SEQ(DisasContext *ctx, arg_SEQ *a)
559 {
560 return do_seq_sne(ctx, a, TCG_COND_EQ);
561 }
562
563 static bool trans_SNE(DisasContext *ctx, arg_SNE *a)
564 {
565 return do_seq_sne(ctx, a, TCG_COND_NE);
566 }
567
568 static bool do_seqi_snei(DisasContext *ctx, const arg_cmpi *a, TCGCond cond)
569 {
570 TCGv_i64 t0;
571
572 t0 = tcg_temp_new_i64();
573 gen_load_gpr(t0, a->rs);
574
575 tcg_gen_setcondi_i64(cond, t0, t0, a->imm);
576 gen_store_gpr(t0, a->rt);
577 return true;
578 }
579
580 static bool trans_SEQI(DisasContext *ctx, arg_SEQI *a)
581 {
582 return do_seqi_snei(ctx, a, TCG_COND_EQ);
583 }
584
585 static bool trans_SNEI(DisasContext *ctx, arg_SNEI *a)
586 {
587 return do_seqi_snei(ctx, a, TCG_COND_NE);
588 }
589
590 static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop)
591 {
592 gen_lx(ctx, a->rd, a->base, a->index, mop);
593
594 return true;
595 }
596
597 TRANS(LBX, trans_lx, MO_SB);
598 TRANS(LBUX, trans_lx, MO_UB);
599 TRANS(LHX, trans_lx, MO_SW);
600 TRANS(LHUX, trans_lx, MO_UW);
601 TRANS(LWX, trans_lx, MO_SL);
602 TRANS(LWUX, trans_lx, MO_UL);
603 TRANS(LDX, trans_lx, MO_UQ);
604
605 static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop)
606 {
607 TCGv_i64 addr = tcg_temp_new_i64();
608 TCGv_i64 value = tcg_temp_new_i64();
609 TCGv_i64 old = tcg_temp_new_i64();
610 MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
611
612 gen_base_offset_addr(ctx, addr, a->base, 0);
613 gen_load_gpr(value, a->rt);
614 tcg_gen_atomic_fetch_add_i64(old, addr, value, ctx->mem_idx, amo);
615 return true;
616 }
617
618 TRANS(SAA, trans_saa, MO_32);
619 TRANS(SAAD, trans_saa, MO_64);
620
621 typedef void AtomicThreeOpFn(TCGv_i64, TCGv_va, TCGv_i64, TCGArg, MemOp);
622
623 static bool do_atomic_la(DisasContext *ctx, arg_la *a,
624 AtomicThreeOpFn *atomic_fn, int64_t imm, MemOp mop)
625 {
626 TCGv_i64 addr = tcg_temp_new_i64();
627 TCGv_i64 old = tcg_temp_new_i64();
628 MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
629
630 gen_base_offset_addr(ctx, addr, a->base, 0);
631
632 atomic_fn(old, addr, tcg_constant_i64(imm), ctx->mem_idx, amo);
633 gen_store_gpr(old, a->rd);
634 return true;
635 }
636
637 static bool do_atomic_laa(DisasContext *ctx, arg_laa *a,
638 AtomicThreeOpFn *atomic_fn, MemOp mop)
639 {
640 TCGv_i64 addr = tcg_temp_new_i64();
641 TCGv_i64 old = tcg_temp_new_i64();
642 TCGv_i64 value = tcg_temp_new_i64();
643 MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
644
645 gen_base_offset_addr(ctx, addr, a->base, 0);
646 gen_load_gpr(value, a->add);
647
648 atomic_fn(old, addr, value, ctx->mem_idx, amo);
649 gen_store_gpr(old, a->rd);
650 return true;
651 }
652
653 TRANS(LAI, do_atomic_la, tcg_gen_atomic_fetch_add_i64, 1, MO_SL);
654 TRANS(LAID, do_atomic_la, tcg_gen_atomic_fetch_add_i64, 1, MO_UQ);
655 TRANS(LAD, do_atomic_la, tcg_gen_atomic_fetch_add_i64, -1, MO_SL);
656 TRANS(LADD, do_atomic_la, tcg_gen_atomic_fetch_add_i64, -1, MO_UQ);
657 TRANS(LAA, do_atomic_laa, tcg_gen_atomic_fetch_add_i64, MO_SL);
658 TRANS(LAAD, do_atomic_laa, tcg_gen_atomic_fetch_add_i64, MO_UQ);
659 TRANS(LAS, do_atomic_la, tcg_gen_atomic_xchg_i64, -1, MO_SL);
660 TRANS(LASD, do_atomic_la, tcg_gen_atomic_xchg_i64, -1, MO_UQ);
661 TRANS(LAC, do_atomic_la, tcg_gen_atomic_xchg_i64, 0, MO_SL);
662 TRANS(LACD, do_atomic_la, tcg_gen_atomic_xchg_i64, 0, MO_UQ);
663 TRANS(LAW, do_atomic_laa, tcg_gen_atomic_xchg_i64, MO_SL);
664 TRANS(LAWD, do_atomic_laa, tcg_gen_atomic_xchg_i64, MO_UQ);
665
666 static bool trans_ZCB(DisasContext *ctx, arg_ZCB *a)
667 {
668 TCGv_i64 addr = tcg_temp_new_i64();
669 TCGv_i64 line = tcg_temp_new_i64();
670 TCGv_i128 zero128 = tcg_zero_i128();
671 const MemOp mop = mo_endian(ctx) | MO_128 | MO_ATOM_NONE;
672
673 gen_base_offset_addr(ctx, addr, a->base, 0);
674
675 /*
676 * QEMU models ZCB/ZCBT as zeroing the containing 128-byte cache line
677 * in guest memory.
678 */
679 tcg_gen_andi_i64(line, addr, ~0x7fULL);
680
681 for (int i = 0; i < 8; i++) {
682 TCGv_i64 slot = tcg_temp_new_i64();
683
684 tcg_gen_addi_i64(slot, line, i * 16);
685 tcg_gen_qemu_st_i128(zero128, slot, ctx->mem_idx, mop);
686 }
687
688 return true;
689 }
690
691 static void octeon_zero_partial_product_state(void)
692 {
693 for (int i = 0; i < OCTEON_MULTIPLIER_REGS; i++) {
694 tcg_gen_movi_i64(oct_p[i], 0);
695 }
696 }
697
698 static bool trans_mtm(DisasContext *ctx, arg_r2 *a, unsigned int index)
699 {
700 /*
701 * Octeon3 two-source MTM forms load lane index from rs and lane index + 3
702 * from rt. Legacy one-source forms encode rt as $zero.
703 */
704 gen_load_gpr(oct_mpl[index], a->rs);
705 gen_load_gpr(oct_mpl[index + 3], a->rt);
706
707 /*
708 * Octeon3 clears MPL1 with a write to MPL0 so that VMULU sequences remain
709 * backward compatible with Octeon2.
710 */
711 if (index == 0) {
712 tcg_gen_movi_i64(oct_mpl[1], 0);
713 }
714
715 octeon_zero_partial_product_state();
716 return true;
717 }
718
719 TRANS(MTM0, trans_mtm, 0);
720 TRANS(MTM1, trans_mtm, 1);
721 TRANS(MTM2, trans_mtm, 2);
722
723 static bool trans_mtp(DisasContext *ctx, arg_r2 *a, unsigned int index)
724 {
725 /*
726 * Octeon3 two-source MTP forms load lane index from rs and lane index + 3
727 * from rt. Legacy one-source forms encode rt as $zero.
728 */
729 gen_load_gpr(oct_p[index], a->rs);
730 gen_load_gpr(oct_p[index + 3], a->rt);
731
732 /*
733 * Octeon3 clears P1 with a write to P0 so that VMULU sequences remain
734 * backward compatible with Octeon2.
735 */
736 if (index == 0) {
737 tcg_gen_movi_i64(oct_p[1], 0);
738 }
739 return true;
740 }
741
742 TRANS(MTP0, trans_mtp, 0);
743 TRANS(MTP1, trans_mtp, 1);
744 TRANS(MTP2, trans_mtp, 2);
745
746 static bool trans_VMULU(DisasContext *ctx, arg_VMULU *a)
747 {
748 TCGv_i64 x[3], y[3], z[3];
749 TCGv_i64 tmp = tcg_temp_new_i64();
750 TCGv_i64 zero = tcg_constant_i64(0);
751
752 z[0] = y[0] = tcg_temp_new_i64();
753 z[1] = y[1] = tcg_temp_new_i64();
754 z[2] = y[2] = tcg_temp_new_i64();
755 x[0] = tcg_temp_new_i64();
756 x[1] = tcg_temp_new_i64();
757 x[2] = zero;
758
759 /* Z = rs * (mpl1 : mpl0) + rt */
760 gen_load_gpr(tmp, a->rs);
761 gen_load_gpr(y[0], a->rt);
762 tcg_gen_mulu2_i64(x[0], x[1], tmp, oct_mpl[0]);
763 tcg_gen_mulu2_i64(y[1], y[2], tmp, oct_mpl[1]);
764 tcg_gen_addN_i64(3, z, y, x);
765
766 /* X == (0 : p1 : p0) */
767 x[0] = oct_p[0];
768 x[1] = oct_p[1];
769
770 /* Y == (p1 : p0 : tmp) */
771 y[0] = tmp;
772 y[1] = oct_p[0];
773 y[2] = oct_p[1];
774
775 /* (p1 : p0 : rd) = Z + (0 : p1 : p0) */
776 tcg_gen_addN_i64(3, y, z, x);
777 gen_store_gpr(tmp, a->rd);
778 return true;
779 }
780
781 static bool trans_VMM0(DisasContext *ctx, arg_VMM0 *a)
782 {
783 TCGv_i64 tmp = tcg_temp_new_i64();
784
785 gen_load_gpr(tmp, a->rs);
786 tcg_gen_mul_i64(oct_mpl[0], oct_mpl[0], tmp);
787 gen_load_gpr(tmp, a->rt);
788 tcg_gen_add_i64(oct_mpl[0], oct_mpl[0], tmp);
789 tcg_gen_add_i64(oct_mpl[0], oct_mpl[0], oct_p[0]);
790 gen_store_gpr(oct_mpl[0], a->rd);
791
792 tcg_gen_movi_i64(oct_mpl[1], 0);
793 octeon_zero_partial_product_state();
794 return true;
795 }
796
797 static bool trans_V3MULU(DisasContext *ctx, arg_V3MULU *a)
798 {
799 TCGv_i64 x[7], y[7], z[7];
800 TCGv_i64 tmp = tcg_temp_new_i64();
801
802 for (int i = 0; i < 7; ++i) {
803 z[i] = tcg_temp_new_i64();
804 y[i] = tcg_temp_new_i64();
805 }
806 memcpy(&x[0], z, 6 * sizeof(TCGv_i64));
807 x[6] = tcg_constant_i64(0);
808
809 /*
810 * Z = rs * mpl -- 64x384->448 bit multiply
811 * Compute even partial products into X and odd partial products into Y.
812 * Include RT into the odd partial products, which are 0 in bits [63:0].
813 */
814 gen_load_gpr(tmp, a->rs);
815 gen_load_gpr(y[0], a->rt);
816 for (int i = 0; i < 6; i += 2) {
817 tcg_gen_mulu2_i64(x[i + 0], x[i + 1], tmp, oct_mpl[i]);
818 tcg_gen_mulu2_i64(y[i + 1], y[i + 2], tmp, oct_mpl[i + 1]);
819 }
820
821 /* Sum even and odd to produce final product, plus rt. */
822 tcg_gen_addN_i64(7, z, x, y);
823
824 /* X == (0 : p5 : p4 : p3 : p2 : p1 : p0) -- x[6] is still 0 */
825 memcpy(&x[0], oct_p, 6 * sizeof(TCGv_i64));
826
827 /* Y == (p5 : p4 : p3 : p2 : p1 : p0 : tmp) */
828 memcpy(&y[1], oct_p, 6 * sizeof(TCGv_i64));
829 y[0] = tmp;
830
831 /* (p* : rd) = (0 : p*) + (rs * mpl + rt) */
832 tcg_gen_addN_i64(7, y, x, z);
833 gen_store_gpr(tmp, a->rd);
834 return true;
835 }
836
837 static bool trans_QMAC(DisasContext *ctx, arg_QMAC *a)
838 {
839 TCGv_i64 t0 = tcg_temp_new_i64();
840 TCGv_i64 t1 = tcg_temp_new_i64();
841
842 gen_load_gpr(t0, a->rt);
843 gen_load_gpr(t1, a->rs);
844
845 /* t0 = rt<0> * rs<lane> * 2 */
846 tcg_gen_ext16s_i64(t0, t0);
847 tcg_gen_sextract_i64(t1, t1, a->lane * 16, 16);
848 tcg_gen_mul_i64(t0, t0, t1);
849 tcg_gen_add_i64(t0, t0, t0);
850
851 /* Saturate -0x8000 * -0x8000 * 2 = 0x80000000 -> 0x7fffffff */
852 tcg_gen_smin_i64(t0, t0, tcg_constant_i64(INT32_MAX));
853
854 /* HI:LO += t0 */
855 tcg_gen_concat32_i64(t1, cpu_LO[0], cpu_HI[0]);
856 tcg_gen_add_i64(t0, t0, t1);
857 tcg_gen_sextract_i64(cpu_LO[0], t0, 0, 32);
858 tcg_gen_sextract_i64(cpu_HI[0], t0, 32, 32);
859 return true;
860 }
861
862 static bool trans_QMACS(DisasContext *ctx, arg_QMACS *a)
863 {
864 TCGv_i64 min32 = tcg_constant_i64(INT32_MIN);
865 TCGv_i64 max32 = tcg_constant_i64(INT32_MAX);
866 TCGv_i64 t0 = tcg_temp_new_i64();
867 TCGv_i64 t1 = tcg_temp_new_i64();
868
869 gen_load_gpr(t0, a->rt);
870 gen_load_gpr(t1, a->rs);
871
872 /* t0 = rt<0> * rs<lane> * 2 */
873 tcg_gen_ext16s_i64(t0, t0);
874 tcg_gen_sextract_i64(t1, t1, a->lane * 16, 16);
875 tcg_gen_mul_i64(t0, t0, t1);
876 tcg_gen_add_i64(t0, t0, t0);
877
878 /*
879 * Saturate -0x8000 * -0x8000 * 2 = 0x80000000 -> 0x7fffffff.
880 * Accumulate overflow in HI[0].
881 */
882 tcg_gen_smin_i64(t1, t0, max32);
883 tcg_gen_setcond_i64(TCG_COND_NE, t0, t0, t1);
884 tcg_gen_or_i64(cpu_HI[0], cpu_HI[0], t0);
885
886 /*
887 * LO = sat32(LO + t0)
888 * Accumulate overflow in HI[0].
889 */
890 tcg_gen_ext32s_i64(t0, cpu_LO[0]);
891 tcg_gen_add_i64(t0, t0, t1);
892 tcg_gen_smin_i64(cpu_LO[0], t0, max32);
893 tcg_gen_smax_i64(cpu_LO[0], cpu_LO[0], min32);
894 tcg_gen_setcond_i64(TCG_COND_NE, t0, t0, cpu_LO[0]);
895 tcg_gen_or_i64(cpu_HI[0], cpu_HI[0], t0);
896 return true;
897 }