Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / target / hexagon / genptr.c
blob90db99024ffb1dbe1ef514c025afab0f1715660e
1 /*
2 * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
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.
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.
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/>.
18 #include "qemu/osdep.h"
19 #include "cpu.h"
20 #include "internal.h"
21 #include "tcg/tcg-op.h"
22 #include "tcg/tcg-op-gvec.h"
23 #include "insn.h"
24 #include "opcodes.h"
25 #include "translate.h"
26 #define QEMU_GENERATE /* Used internally by macros.h */
27 #include "macros.h"
28 #include "mmvec/macros.h"
29 #undef QEMU_GENERATE
30 #include "gen_tcg.h"
31 #include "gen_tcg_hvx.h"
32 #include "genptr.h"
34 TCGv gen_read_reg(TCGv result, int num)
36 tcg_gen_mov_tl(result, hex_gpr[num]);
37 return result;
40 TCGv gen_read_preg(TCGv pred, uint8_t num)
42 tcg_gen_mov_tl(pred, hex_pred[num]);
43 return pred;
46 #define IMMUTABLE (~0)
48 static const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = {
49 [HEX_REG_USR] = 0xc13000c0,
50 [HEX_REG_PC] = IMMUTABLE,
51 [HEX_REG_GP] = 0x3f,
52 [HEX_REG_UPCYCLELO] = IMMUTABLE,
53 [HEX_REG_UPCYCLEHI] = IMMUTABLE,
54 [HEX_REG_UTIMERLO] = IMMUTABLE,
55 [HEX_REG_UTIMERHI] = IMMUTABLE,
58 static inline void gen_masked_reg_write(TCGv new_val, TCGv cur_val,
59 target_ulong reg_mask)
61 if (reg_mask) {
62 TCGv tmp = tcg_temp_new();
64 /* new_val = (new_val & ~reg_mask) | (cur_val & reg_mask) */
65 tcg_gen_andi_tl(new_val, new_val, ~reg_mask);
66 tcg_gen_andi_tl(tmp, cur_val, reg_mask);
67 tcg_gen_or_tl(new_val, new_val, tmp);
69 tcg_temp_free(tmp);
73 static inline void gen_log_predicated_reg_write(int rnum, TCGv val,
74 uint32_t slot)
76 TCGv zero = tcg_constant_tl(0);
77 TCGv slot_mask = tcg_temp_new();
79 tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
80 tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero,
81 val, hex_new_value[rnum]);
82 if (HEX_DEBUG) {
84 * Do this so HELPER(debug_commit_end) will know
86 * Note that slot_mask indicates the value is not written
87 * (i.e., slot was cancelled), so we create a true/false value before
88 * or'ing with hex_reg_written[rnum].
90 tcg_gen_setcond_tl(TCG_COND_EQ, slot_mask, slot_mask, zero);
91 tcg_gen_or_tl(hex_reg_written[rnum], hex_reg_written[rnum], slot_mask);
94 tcg_temp_free(slot_mask);
97 void gen_log_reg_write(int rnum, TCGv val)
99 const target_ulong reg_mask = reg_immut_masks[rnum];
101 gen_masked_reg_write(val, hex_gpr[rnum], reg_mask);
102 tcg_gen_mov_tl(hex_new_value[rnum], val);
103 if (HEX_DEBUG) {
104 /* Do this so HELPER(debug_commit_end) will know */
105 tcg_gen_movi_tl(hex_reg_written[rnum], 1);
109 static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val,
110 uint32_t slot)
112 TCGv val32 = tcg_temp_new();
113 TCGv zero = tcg_constant_tl(0);
114 TCGv slot_mask = tcg_temp_new();
116 tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
117 /* Low word */
118 tcg_gen_extrl_i64_i32(val32, val);
119 tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum],
120 slot_mask, zero,
121 val32, hex_new_value[rnum]);
122 /* High word */
123 tcg_gen_extrh_i64_i32(val32, val);
124 tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum + 1],
125 slot_mask, zero,
126 val32, hex_new_value[rnum + 1]);
127 if (HEX_DEBUG) {
129 * Do this so HELPER(debug_commit_end) will know
131 * Note that slot_mask indicates the value is not written
132 * (i.e., slot was cancelled), so we create a true/false value before
133 * or'ing with hex_reg_written[rnum].
135 tcg_gen_setcond_tl(TCG_COND_EQ, slot_mask, slot_mask, zero);
136 tcg_gen_or_tl(hex_reg_written[rnum], hex_reg_written[rnum], slot_mask);
137 tcg_gen_or_tl(hex_reg_written[rnum + 1], hex_reg_written[rnum + 1],
138 slot_mask);
141 tcg_temp_free(val32);
142 tcg_temp_free(slot_mask);
145 static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
147 const target_ulong reg_mask_low = reg_immut_masks[rnum];
148 const target_ulong reg_mask_high = reg_immut_masks[rnum + 1];
149 TCGv val32 = tcg_temp_new();
151 /* Low word */
152 tcg_gen_extrl_i64_i32(val32, val);
153 gen_masked_reg_write(val32, hex_gpr[rnum], reg_mask_low);
154 tcg_gen_mov_tl(hex_new_value[rnum], val32);
155 if (HEX_DEBUG) {
156 /* Do this so HELPER(debug_commit_end) will know */
157 tcg_gen_movi_tl(hex_reg_written[rnum], 1);
160 /* High word */
161 tcg_gen_extrh_i64_i32(val32, val);
162 gen_masked_reg_write(val32, hex_gpr[rnum + 1], reg_mask_high);
163 tcg_gen_mov_tl(hex_new_value[rnum + 1], val32);
164 if (HEX_DEBUG) {
165 /* Do this so HELPER(debug_commit_end) will know */
166 tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1);
169 tcg_temp_free(val32);
172 void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
174 TCGv base_val = tcg_temp_new();
176 tcg_gen_andi_tl(base_val, val, 0xff);
179 * Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual
181 * Multiple writes to the same preg are and'ed together
182 * If this is the first predicate write in the packet, do a
183 * straight assignment. Otherwise, do an and.
185 if (!test_bit(pnum, ctx->pregs_written)) {
186 tcg_gen_mov_tl(hex_new_pred_value[pnum], base_val);
187 } else {
188 tcg_gen_and_tl(hex_new_pred_value[pnum],
189 hex_new_pred_value[pnum], base_val);
191 tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
193 tcg_temp_free(base_val);
196 static inline void gen_read_p3_0(TCGv control_reg)
198 tcg_gen_movi_tl(control_reg, 0);
199 for (int i = 0; i < NUM_PREGS; i++) {
200 tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8);
205 * Certain control registers require special handling on read
206 * HEX_REG_P3_0_ALIASED aliased to the predicate registers
207 * -> concat the 4 predicate registers together
208 * HEX_REG_PC actual value stored in DisasContext
209 * -> assign from ctx->base.pc_next
210 * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext
211 * -> add current TB changes to existing reg value
213 static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
214 TCGv dest)
216 if (reg_num == HEX_REG_P3_0_ALIASED) {
217 gen_read_p3_0(dest);
218 } else if (reg_num == HEX_REG_PC) {
219 tcg_gen_movi_tl(dest, ctx->base.pc_next);
220 } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
221 tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT],
222 ctx->num_packets);
223 } else if (reg_num == HEX_REG_QEMU_INSN_CNT) {
224 tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT],
225 ctx->num_insns);
226 } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
227 tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_HVX_CNT],
228 ctx->num_hvx_insns);
229 } else {
230 tcg_gen_mov_tl(dest, hex_gpr[reg_num]);
234 static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
235 TCGv_i64 dest)
237 if (reg_num == HEX_REG_P3_0_ALIASED) {
238 TCGv p3_0 = tcg_temp_new();
239 gen_read_p3_0(p3_0);
240 tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
241 tcg_temp_free(p3_0);
242 } else if (reg_num == HEX_REG_PC - 1) {
243 TCGv pc = tcg_constant_tl(ctx->base.pc_next);
244 tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc);
245 } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
246 TCGv pkt_cnt = tcg_temp_new();
247 TCGv insn_cnt = tcg_temp_new();
248 tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT],
249 ctx->num_packets);
250 tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT],
251 ctx->num_insns);
252 tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt);
253 tcg_temp_free(pkt_cnt);
254 tcg_temp_free(insn_cnt);
255 } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
256 TCGv hvx_cnt = tcg_temp_new();
257 tcg_gen_addi_tl(hvx_cnt, hex_gpr[HEX_REG_QEMU_HVX_CNT],
258 ctx->num_hvx_insns);
259 tcg_gen_concat_i32_i64(dest, hvx_cnt, hex_gpr[reg_num + 1]);
260 tcg_temp_free(hvx_cnt);
261 } else {
262 tcg_gen_concat_i32_i64(dest,
263 hex_gpr[reg_num],
264 hex_gpr[reg_num + 1]);
268 static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg)
270 TCGv hex_p8 = tcg_temp_new();
271 for (int i = 0; i < NUM_PREGS; i++) {
272 tcg_gen_extract_tl(hex_p8, control_reg, i * 8, 8);
273 gen_log_pred_write(ctx, i, hex_p8);
274 ctx_log_pred_write(ctx, i);
276 tcg_temp_free(hex_p8);
280 * Certain control registers require special handling on write
281 * HEX_REG_P3_0_ALIASED aliased to the predicate registers
282 * -> break the value across 4 predicate registers
283 * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext
284 * -> clear the changes
286 static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
287 TCGv val)
289 if (reg_num == HEX_REG_P3_0_ALIASED) {
290 gen_write_p3_0(ctx, val);
291 } else {
292 gen_log_reg_write(reg_num, val);
293 ctx_log_reg_write(ctx, reg_num);
294 if (reg_num == HEX_REG_QEMU_PKT_CNT) {
295 ctx->num_packets = 0;
297 if (reg_num == HEX_REG_QEMU_INSN_CNT) {
298 ctx->num_insns = 0;
300 if (reg_num == HEX_REG_QEMU_HVX_CNT) {
301 ctx->num_hvx_insns = 0;
306 static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
307 TCGv_i64 val)
309 if (reg_num == HEX_REG_P3_0_ALIASED) {
310 TCGv val32 = tcg_temp_new();
311 tcg_gen_extrl_i64_i32(val32, val);
312 gen_write_p3_0(ctx, val32);
313 tcg_gen_extrh_i64_i32(val32, val);
314 gen_log_reg_write(reg_num + 1, val32);
315 tcg_temp_free(val32);
316 ctx_log_reg_write(ctx, reg_num + 1);
317 } else {
318 gen_log_reg_write_pair(reg_num, val);
319 ctx_log_reg_write_pair(ctx, reg_num);
320 if (reg_num == HEX_REG_QEMU_PKT_CNT) {
321 ctx->num_packets = 0;
322 ctx->num_insns = 0;
324 if (reg_num == HEX_REG_QEMU_HVX_CNT) {
325 ctx->num_hvx_insns = 0;
330 TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign)
332 if (sign) {
333 tcg_gen_sextract_tl(result, src, N * 8, 8);
334 } else {
335 tcg_gen_extract_tl(result, src, N * 8, 8);
337 return result;
340 TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign)
342 TCGv_i64 res64 = tcg_temp_new_i64();
343 if (sign) {
344 tcg_gen_sextract_i64(res64, src, N * 8, 8);
345 } else {
346 tcg_gen_extract_i64(res64, src, N * 8, 8);
348 tcg_gen_extrl_i64_i32(result, res64);
349 tcg_temp_free_i64(res64);
351 return result;
354 TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign)
356 if (sign) {
357 tcg_gen_sextract_tl(result, src, N * 16, 16);
358 } else {
359 tcg_gen_extract_tl(result, src, N * 16, 16);
361 return result;
364 void gen_set_half(int N, TCGv result, TCGv src)
366 tcg_gen_deposit_tl(result, result, src, N * 16, 16);
369 void gen_set_half_i64(int N, TCGv_i64 result, TCGv src)
371 TCGv_i64 src64 = tcg_temp_new_i64();
372 tcg_gen_extu_i32_i64(src64, src);
373 tcg_gen_deposit_i64(result, result, src64, N * 16, 16);
374 tcg_temp_free_i64(src64);
377 void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src)
379 TCGv_i64 src64 = tcg_temp_new_i64();
380 tcg_gen_extu_i32_i64(src64, src);
381 tcg_gen_deposit_i64(result, result, src64, N * 8, 8);
382 tcg_temp_free_i64(src64);
385 static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index)
387 tcg_gen_qemu_ld32u(dest, vaddr, mem_index);
388 tcg_gen_mov_tl(hex_llsc_addr, vaddr);
389 tcg_gen_mov_tl(hex_llsc_val, dest);
392 static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index)
394 tcg_gen_qemu_ld64(dest, vaddr, mem_index);
395 tcg_gen_mov_tl(hex_llsc_addr, vaddr);
396 tcg_gen_mov_i64(hex_llsc_val_i64, dest);
399 static inline void gen_store_conditional4(DisasContext *ctx,
400 TCGv pred, TCGv vaddr, TCGv src)
402 TCGLabel *fail = gen_new_label();
403 TCGLabel *done = gen_new_label();
404 TCGv one, zero, tmp;
406 tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
408 one = tcg_constant_tl(0xff);
409 zero = tcg_constant_tl(0);
410 tmp = tcg_temp_new();
411 tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src,
412 ctx->mem_idx, MO_32);
413 tcg_gen_movcond_tl(TCG_COND_EQ, pred, tmp, hex_llsc_val,
414 one, zero);
415 tcg_temp_free(tmp);
416 tcg_gen_br(done);
418 gen_set_label(fail);
419 tcg_gen_movi_tl(pred, 0);
421 gen_set_label(done);
422 tcg_gen_movi_tl(hex_llsc_addr, ~0);
425 static inline void gen_store_conditional8(DisasContext *ctx,
426 TCGv pred, TCGv vaddr, TCGv_i64 src)
428 TCGLabel *fail = gen_new_label();
429 TCGLabel *done = gen_new_label();
430 TCGv_i64 one, zero, tmp;
432 tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
434 one = tcg_constant_i64(0xff);
435 zero = tcg_constant_i64(0);
436 tmp = tcg_temp_new_i64();
437 tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src,
438 ctx->mem_idx, MO_64);
439 tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64,
440 one, zero);
441 tcg_gen_extrl_i64_i32(pred, tmp);
442 tcg_temp_free_i64(tmp);
443 tcg_gen_br(done);
445 gen_set_label(fail);
446 tcg_gen_movi_tl(pred, 0);
448 gen_set_label(done);
449 tcg_gen_movi_tl(hex_llsc_addr, ~0);
452 void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot)
454 tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
455 tcg_gen_movi_tl(hex_store_width[slot], width);
456 tcg_gen_mov_tl(hex_store_val32[slot], src);
459 void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
461 gen_store32(vaddr, src, 1, slot);
464 void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot)
466 TCGv tmp = tcg_constant_tl(src);
467 gen_store1(cpu_env, vaddr, tmp, slot);
470 void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
472 gen_store32(vaddr, src, 2, slot);
475 void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot)
477 TCGv tmp = tcg_constant_tl(src);
478 gen_store2(cpu_env, vaddr, tmp, slot);
481 void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
483 gen_store32(vaddr, src, 4, slot);
486 void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot)
488 TCGv tmp = tcg_constant_tl(src);
489 gen_store4(cpu_env, vaddr, tmp, slot);
492 void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, uint32_t slot)
494 tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
495 tcg_gen_movi_tl(hex_store_width[slot], 8);
496 tcg_gen_mov_i64(hex_store_val64[slot], src);
499 void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, uint32_t slot)
501 TCGv_i64 tmp = tcg_constant_i64(src);
502 gen_store8(cpu_env, vaddr, tmp, slot);
505 TCGv gen_8bitsof(TCGv result, TCGv value)
507 TCGv zero = tcg_constant_tl(0);
508 TCGv ones = tcg_constant_tl(0xff);
509 tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero);
511 return result;
514 static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
515 TCGCond cond, TCGv pred)
517 TCGLabel *pred_false = NULL;
518 if (cond != TCG_COND_ALWAYS) {
519 pred_false = gen_new_label();
520 tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
523 if (ctx->pkt->pkt_has_multi_cof) {
524 /* If there are multiple branches in a packet, ignore the second one */
525 tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
526 hex_branch_taken, tcg_constant_tl(0),
527 hex_gpr[HEX_REG_PC], addr);
528 tcg_gen_movi_tl(hex_branch_taken, 1);
529 } else {
530 tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
533 if (cond != TCG_COND_ALWAYS) {
534 gen_set_label(pred_false);
538 static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
539 TCGCond cond, TCGv pred)
541 target_ulong dest = ctx->pkt->pc + pc_off;
542 if (ctx->pkt->pkt_has_multi_cof) {
543 gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
544 } else {
545 /* Defer this jump to the end of the TB */
546 ctx->branch_cond = TCG_COND_ALWAYS;
547 if (pred != NULL) {
548 ctx->branch_cond = cond;
549 tcg_gen_mov_tl(hex_branch_taken, pred);
551 ctx->branch_dest = dest;
555 void gen_set_usr_field(int field, TCGv val)
557 tcg_gen_deposit_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR],
558 val,
559 reg_field_info[field].offset,
560 reg_field_info[field].width);
563 void gen_set_usr_fieldi(int field, int x)
565 if (reg_field_info[field].width == 1) {
566 target_ulong bit = 1 << reg_field_info[field].offset;
567 if ((x & 1) == 1) {
568 tcg_gen_ori_tl(hex_new_value[HEX_REG_USR],
569 hex_new_value[HEX_REG_USR],
570 bit);
571 } else {
572 tcg_gen_andi_tl(hex_new_value[HEX_REG_USR],
573 hex_new_value[HEX_REG_USR],
574 ~bit);
576 } else {
577 TCGv val = tcg_constant_tl(x);
578 gen_set_usr_field(field, val);
582 static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
584 TCGv one = tcg_constant_tl(0xff);
585 TCGv zero = tcg_constant_tl(0);
587 tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
590 static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
591 TCGCond cond, TCGv pred)
593 gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
596 static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
597 int pc_off)
599 gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
602 static void gen_cmpnd_cmp_jmp(DisasContext *ctx,
603 int pnum, TCGCond cond1, TCGv arg1, TCGv arg2,
604 TCGCond cond2, int pc_off)
606 if (ctx->insn->part1) {
607 TCGv pred = tcg_temp_new();
608 gen_compare(cond1, pred, arg1, arg2);
609 gen_log_pred_write(ctx, pnum, pred);
610 tcg_temp_free(pred);
611 } else {
612 TCGv pred = tcg_temp_new();
613 tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
614 gen_cond_jump(ctx, cond2, pred, pc_off);
615 tcg_temp_free(pred);
619 static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
620 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
621 int pc_off)
623 gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
626 static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
627 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
628 int pc_off)
630 gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
633 static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
634 int pnum, TCGCond cond, TCGv arg1, int arg2,
635 int pc_off)
637 TCGv tmp = tcg_constant_tl(arg2);
638 gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
641 static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
642 int pnum, TCGCond cond, TCGv arg1, int arg2,
643 int pc_off)
645 TCGv tmp = tcg_constant_tl(arg2);
646 gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
649 static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
650 TCGv arg, int pc_off)
652 gen_cmpnd_cmpi_jmp_t(ctx, pnum, cond, arg, -1, pc_off);
655 static void gen_cmpnd_cmp_n1_jmp_f(DisasContext *ctx, int pnum, TCGCond cond,
656 TCGv arg, int pc_off)
658 gen_cmpnd_cmpi_jmp_f(ctx, pnum, cond, arg, -1, pc_off);
661 static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
662 int pnum, TCGv arg, TCGCond cond, int pc_off)
664 if (ctx->insn->part1) {
665 TCGv pred = tcg_temp_new();
666 tcg_gen_andi_tl(pred, arg, 1);
667 gen_8bitsof(pred, pred);
668 gen_log_pred_write(ctx, pnum, pred);
669 tcg_temp_free(pred);
670 } else {
671 TCGv pred = tcg_temp_new();
672 tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
673 gen_cond_jump(ctx, cond, pred, pc_off);
674 tcg_temp_free(pred);
678 static void gen_testbit0_jumpnv(DisasContext *ctx,
679 TCGv arg, TCGCond cond, int pc_off)
681 TCGv pred = tcg_temp_new();
682 tcg_gen_andi_tl(pred, arg, 1);
683 gen_cond_jump(ctx, cond, pred, pc_off);
684 tcg_temp_free(pred);
687 static void gen_jump(DisasContext *ctx, int pc_off)
689 gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
692 static void gen_jumpr(DisasContext *ctx, TCGv new_pc)
694 gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
697 static void gen_call(DisasContext *ctx, int pc_off)
699 TCGv next_PC =
700 tcg_constant_tl(ctx->pkt->pc + ctx->pkt->encod_pkt_size_in_bytes);
701 gen_log_reg_write(HEX_REG_LR, next_PC);
702 gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
705 static void gen_cond_call(DisasContext *ctx, TCGv pred,
706 TCGCond cond, int pc_off)
708 TCGv next_PC;
709 TCGv lsb = tcg_temp_local_new();
710 TCGLabel *skip = gen_new_label();
711 tcg_gen_andi_tl(lsb, pred, 1);
712 gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
713 tcg_gen_brcondi_tl(cond, lsb, 0, skip);
714 tcg_temp_free(lsb);
715 next_PC =
716 tcg_constant_tl(ctx->pkt->pc + ctx->pkt->encod_pkt_size_in_bytes);
717 gen_log_reg_write(HEX_REG_LR, next_PC);
718 gen_set_label(skip);
721 static void gen_endloop0(DisasContext *ctx)
723 TCGv lpcfg = tcg_temp_local_new();
725 GET_USR_FIELD(USR_LPCFG, lpcfg);
728 * if (lpcfg == 1) {
729 * hex_new_pred_value[3] = 0xff;
730 * hex_pred_written |= 1 << 3;
733 TCGLabel *label1 = gen_new_label();
734 tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
736 tcg_gen_movi_tl(hex_new_pred_value[3], 0xff);
737 tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << 3);
739 gen_set_label(label1);
742 * if (lpcfg) {
743 * SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
746 TCGLabel *label2 = gen_new_label();
747 tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
749 tcg_gen_subi_tl(lpcfg, lpcfg, 1);
750 SET_USR_FIELD(USR_LPCFG, lpcfg);
752 gen_set_label(label2);
755 * If we're in a tight loop, we'll do this at the end of the TB to take
756 * advantage of direct block chaining.
758 if (!ctx->is_tight_loop) {
760 * if (hex_gpr[HEX_REG_LC0] > 1) {
761 * PC = hex_gpr[HEX_REG_SA0];
762 * hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
765 TCGLabel *label3 = gen_new_label();
766 tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
768 gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
769 tcg_gen_subi_tl(hex_new_value[HEX_REG_LC0],
770 hex_gpr[HEX_REG_LC0], 1);
772 gen_set_label(label3);
775 tcg_temp_free(lpcfg);
778 static void gen_cmp_jumpnv(DisasContext *ctx,
779 TCGCond cond, TCGv val, TCGv src, int pc_off)
781 TCGv pred = tcg_temp_new();
782 tcg_gen_setcond_tl(cond, pred, val, src);
783 gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
784 tcg_temp_free(pred);
787 static void gen_cmpi_jumpnv(DisasContext *ctx,
788 TCGCond cond, TCGv val, int src, int pc_off)
790 TCGv pred = tcg_temp_new();
791 tcg_gen_setcondi_tl(cond, pred, val, src);
792 gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
793 tcg_temp_free(pred);
796 /* Shift left with saturation */
797 static void gen_shl_sat(TCGv dst, TCGv src, TCGv shift_amt)
799 TCGv sh32 = tcg_temp_new();
800 TCGv dst_sar = tcg_temp_new();
801 TCGv ovf = tcg_temp_new();
802 TCGv satval = tcg_temp_new();
803 TCGv min = tcg_constant_tl(0x80000000);
804 TCGv max = tcg_constant_tl(0x7fffffff);
807 * Possible values for shift_amt are 0 .. 64
808 * We need special handling for values above 31
810 * sh32 = shift & 31;
811 * dst = sh32 == shift ? src : 0;
812 * dst <<= sh32;
813 * dst_sar = dst >> sh32;
814 * satval = src < 0 ? min : max;
815 * if (dst_asr != src) {
816 * usr.OVF |= 1;
817 * dst = satval;
821 tcg_gen_andi_tl(sh32, shift_amt, 31);
822 tcg_gen_movcond_tl(TCG_COND_EQ, dst, sh32, shift_amt,
823 src, tcg_constant_tl(0));
824 tcg_gen_shl_tl(dst, dst, sh32);
825 tcg_gen_sar_tl(dst_sar, dst, sh32);
826 tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
828 tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
829 tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
830 tcg_gen_or_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR], ovf);
832 tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, dst, satval);
834 tcg_temp_free(sh32);
835 tcg_temp_free(dst_sar);
836 tcg_temp_free(ovf);
837 tcg_temp_free(satval);
840 static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
843 * Shift arithmetic right
844 * Robust when shift_amt is >31 bits
846 TCGv tmp = tcg_temp_new();
847 tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31));
848 tcg_gen_sar_tl(dst, src, tmp);
849 tcg_temp_free(tmp);
852 /* Bidirectional shift right with saturation */
853 static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
855 TCGv shift_amt = tcg_temp_local_new();
856 TCGLabel *positive = gen_new_label();
857 TCGLabel *done = gen_new_label();
859 tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
860 tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
862 /* Negative shift amount => shift left */
863 tcg_gen_neg_tl(shift_amt, shift_amt);
864 gen_shl_sat(RdV, RsV, shift_amt);
865 tcg_gen_br(done);
867 gen_set_label(positive);
868 /* Positive shift amount => shift right */
869 gen_sar(RdV, RsV, shift_amt);
871 gen_set_label(done);
873 tcg_temp_free(shift_amt);
876 /* Bidirectional shift left with saturation */
877 static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
879 TCGv shift_amt = tcg_temp_local_new();
880 TCGLabel *positive = gen_new_label();
881 TCGLabel *done = gen_new_label();
883 tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
884 tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
886 /* Negative shift amount => shift right */
887 tcg_gen_neg_tl(shift_amt, shift_amt);
888 gen_sar(RdV, RsV, shift_amt);
889 tcg_gen_br(done);
891 gen_set_label(positive);
892 /* Positive shift amount => shift left */
893 gen_shl_sat(RdV, RsV, shift_amt);
895 gen_set_label(done);
897 tcg_temp_free(shift_amt);
900 static intptr_t vreg_src_off(DisasContext *ctx, int num)
902 intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
904 if (test_bit(num, ctx->vregs_select)) {
905 offset = ctx_future_vreg_off(ctx, num, 1, false);
907 if (test_bit(num, ctx->vregs_updated_tmp)) {
908 offset = ctx_tmp_vreg_off(ctx, num, 1, false);
910 return offset;
913 static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
914 VRegWriteType type, int slot_num,
915 bool is_predicated)
917 TCGLabel *label_end = NULL;
918 intptr_t dstoff;
920 if (is_predicated) {
921 TCGv cancelled = tcg_temp_local_new();
922 label_end = gen_new_label();
924 /* Don't do anything if the slot was cancelled */
925 tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
926 tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
927 tcg_temp_free(cancelled);
930 if (type != EXT_TMP) {
931 dstoff = ctx_future_vreg_off(ctx, num, 1, true);
932 tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
933 sizeof(MMVector), sizeof(MMVector));
934 tcg_gen_ori_tl(hex_VRegs_updated, hex_VRegs_updated, 1 << num);
935 } else {
936 dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
937 tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
938 sizeof(MMVector), sizeof(MMVector));
941 if (is_predicated) {
942 gen_set_label(label_end);
946 static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
947 VRegWriteType type, int slot_num,
948 bool is_predicated)
950 gen_log_vreg_write(ctx, srcoff, num ^ 0, type, slot_num, is_predicated);
951 srcoff += sizeof(MMVector);
952 gen_log_vreg_write(ctx, srcoff, num ^ 1, type, slot_num, is_predicated);
955 static void gen_log_qreg_write(intptr_t srcoff, int num, int vnew,
956 int slot_num, bool is_predicated)
958 TCGLabel *label_end = NULL;
959 intptr_t dstoff;
961 if (is_predicated) {
962 TCGv cancelled = tcg_temp_local_new();
963 label_end = gen_new_label();
965 /* Don't do anything if the slot was cancelled */
966 tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
967 tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
968 tcg_temp_free(cancelled);
971 dstoff = offsetof(CPUHexagonState, future_QRegs[num]);
972 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMQReg), sizeof(MMQReg));
974 if (is_predicated) {
975 tcg_gen_ori_tl(hex_QRegs_updated, hex_QRegs_updated, 1 << num);
976 gen_set_label(label_end);
980 static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
981 bool aligned)
983 TCGv_i64 tmp = tcg_temp_new_i64();
984 if (aligned) {
985 tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1));
987 for (int i = 0; i < sizeof(MMVector) / 8; i++) {
988 tcg_gen_qemu_ld64(tmp, src, ctx->mem_idx);
989 tcg_gen_addi_tl(src, src, 8);
990 tcg_gen_st_i64(tmp, cpu_env, dstoff + i * 8);
992 tcg_temp_free_i64(tmp);
995 static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
996 int slot, bool aligned)
998 intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
999 intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
1001 if (is_gather_store_insn(ctx)) {
1002 TCGv sl = tcg_constant_tl(slot);
1003 gen_helper_gather_store(cpu_env, EA, sl);
1004 return;
1007 tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
1008 if (aligned) {
1009 tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
1010 ~((int32_t)sizeof(MMVector) - 1));
1011 } else {
1012 tcg_gen_mov_tl(hex_vstore_addr[slot], EA);
1014 tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
1016 /* Copy the data to the vstore buffer */
1017 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
1018 /* Set the mask to all 1's */
1019 tcg_gen_gvec_dup_imm(MO_64, maskoff, sizeof(MMQReg), sizeof(MMQReg), ~0LL);
1022 static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
1023 intptr_t bitsoff, int slot, bool invert)
1025 intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
1026 intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
1028 tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
1029 tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
1030 ~((int32_t)sizeof(MMVector) - 1));
1031 tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
1033 /* Copy the data to the vstore buffer */
1034 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
1035 /* Copy the mask */
1036 tcg_gen_gvec_mov(MO_64, maskoff, bitsoff, sizeof(MMQReg), sizeof(MMQReg));
1037 if (invert) {
1038 tcg_gen_gvec_not(MO_64, maskoff, maskoff,
1039 sizeof(MMQReg), sizeof(MMQReg));
1043 static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
1045 TCGv_i64 tmp = tcg_temp_new_i64();
1046 TCGv_i64 word = tcg_temp_new_i64();
1047 TCGv_i64 bits = tcg_temp_new_i64();
1048 TCGv_i64 mask = tcg_temp_new_i64();
1049 TCGv_i64 zero = tcg_constant_i64(0);
1050 TCGv_i64 ones = tcg_constant_i64(~0);
1052 for (int i = 0; i < sizeof(MMVector) / 8; i++) {
1053 tcg_gen_ld_i64(tmp, cpu_env, srcoff + i * 8);
1054 tcg_gen_movi_i64(mask, 0);
1056 for (int j = 0; j < 8; j += size) {
1057 tcg_gen_extract_i64(word, tmp, j * 8, size * 8);
1058 tcg_gen_movcond_i64(TCG_COND_NE, bits, word, zero, ones, zero);
1059 tcg_gen_deposit_i64(mask, mask, bits, j, size);
1062 tcg_gen_st8_i64(mask, cpu_env, dstoff + i);
1064 tcg_temp_free_i64(tmp);
1065 tcg_temp_free_i64(word);
1066 tcg_temp_free_i64(bits);
1067 tcg_temp_free_i64(mask);
1070 void probe_noshuf_load(TCGv va, int s, int mi)
1072 TCGv size = tcg_constant_tl(s);
1073 TCGv mem_idx = tcg_constant_tl(mi);
1074 gen_helper_probe_noshuf_load(cpu_env, va, size, mem_idx);
1078 * Note: Since this function might branch, `val` is
1079 * required to be a `tcg_temp_local`.
1081 void gen_set_usr_field_if(int field, TCGv val)
1083 /* Sets the USR field if `val` is non-zero */
1084 if (reg_field_info[field].width == 1) {
1085 TCGv tmp = tcg_temp_new();
1086 tcg_gen_extract_tl(tmp, val, 0, reg_field_info[field].width);
1087 tcg_gen_shli_tl(tmp, tmp, reg_field_info[field].offset);
1088 tcg_gen_or_tl(hex_new_value[HEX_REG_USR],
1089 hex_new_value[HEX_REG_USR],
1090 tmp);
1091 tcg_temp_free(tmp);
1092 } else {
1093 TCGLabel *skip_label = gen_new_label();
1094 tcg_gen_brcondi_tl(TCG_COND_EQ, val, 0, skip_label);
1095 gen_set_usr_field(field, val);
1096 gen_set_label(skip_label);
1100 void gen_sat_i32(TCGv dest, TCGv source, int width)
1102 TCGv max_val = tcg_constant_tl((1 << (width - 1)) - 1);
1103 TCGv min_val = tcg_constant_tl(-(1 << (width - 1)));
1104 tcg_gen_smin_tl(dest, source, max_val);
1105 tcg_gen_smax_tl(dest, dest, min_val);
1108 void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
1110 gen_sat_i32(dest, source, width);
1111 tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, dest);
1114 void gen_satu_i32(TCGv dest, TCGv source, int width)
1116 TCGv max_val = tcg_constant_tl((1 << width) - 1);
1117 TCGv zero = tcg_constant_tl(0);
1118 tcg_gen_movcond_tl(TCG_COND_GTU, dest, source, max_val, max_val, source);
1119 tcg_gen_movcond_tl(TCG_COND_LT, dest, source, zero, zero, dest);
1122 void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
1124 gen_satu_i32(dest, source, width);
1125 tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, dest);
1128 void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
1130 TCGv_i64 max_val = tcg_constant_i64((1LL << (width - 1)) - 1LL);
1131 TCGv_i64 min_val = tcg_constant_i64(-(1LL << (width - 1)));
1132 tcg_gen_smin_i64(dest, source, max_val);
1133 tcg_gen_smax_i64(dest, dest, min_val);
1136 void gen_sat_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
1138 TCGv_i64 ovfl_64;
1139 gen_sat_i64(dest, source, width);
1140 ovfl_64 = tcg_temp_new_i64();
1141 tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, dest, source);
1142 tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
1143 tcg_temp_free_i64(ovfl_64);
1146 void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width)
1148 TCGv_i64 max_val = tcg_constant_i64((1LL << width) - 1LL);
1149 TCGv_i64 zero = tcg_constant_i64(0);
1150 tcg_gen_movcond_i64(TCG_COND_GTU, dest, source, max_val, max_val, source);
1151 tcg_gen_movcond_i64(TCG_COND_LT, dest, source, zero, zero, dest);
1154 void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
1156 TCGv_i64 ovfl_64;
1157 gen_satu_i64(dest, source, width);
1158 ovfl_64 = tcg_temp_new_i64();
1159 tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, dest, source);
1160 tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
1161 tcg_temp_free_i64(ovfl_64);
1164 /* Implements the fADDSAT64 macro in TCG */
1165 void gen_add_sat_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
1167 TCGv_i64 sum = tcg_temp_local_new_i64();
1168 TCGv_i64 xor = tcg_temp_new_i64();
1169 TCGv_i64 cond1 = tcg_temp_new_i64();
1170 TCGv_i64 cond2 = tcg_temp_local_new_i64();
1171 TCGv_i64 cond3 = tcg_temp_new_i64();
1172 TCGv_i64 mask = tcg_constant_i64(0x8000000000000000ULL);
1173 TCGv_i64 max_pos = tcg_constant_i64(0x7FFFFFFFFFFFFFFFLL);
1174 TCGv_i64 max_neg = tcg_constant_i64(0x8000000000000000LL);
1175 TCGv_i64 zero = tcg_constant_i64(0);
1176 TCGLabel *no_ovfl_label = gen_new_label();
1177 TCGLabel *ovfl_label = gen_new_label();
1178 TCGLabel *ret_label = gen_new_label();
1180 tcg_gen_add_i64(sum, a, b);
1181 tcg_gen_xor_i64(xor, a, b);
1183 /* if (xor & mask) */
1184 tcg_gen_and_i64(cond1, xor, mask);
1185 tcg_temp_free_i64(xor);
1186 tcg_gen_brcondi_i64(TCG_COND_NE, cond1, 0, no_ovfl_label);
1187 tcg_temp_free_i64(cond1);
1189 /* else if ((a ^ sum) & mask) */
1190 tcg_gen_xor_i64(cond2, a, sum);
1191 tcg_gen_and_i64(cond2, cond2, mask);
1192 tcg_gen_brcondi_i64(TCG_COND_NE, cond2, 0, ovfl_label);
1193 tcg_temp_free_i64(cond2);
1194 /* fallthrough to no_ovfl_label branch */
1196 /* if branch */
1197 gen_set_label(no_ovfl_label);
1198 tcg_gen_mov_i64(ret, sum);
1199 tcg_gen_br(ret_label);
1201 /* else if branch */
1202 gen_set_label(ovfl_label);
1203 tcg_gen_and_i64(cond3, sum, mask);
1204 tcg_temp_free_i64(mask);
1205 tcg_temp_free_i64(sum);
1206 tcg_gen_movcond_i64(TCG_COND_NE, ret, cond3, zero, max_pos, max_neg);
1207 tcg_temp_free_i64(cond3);
1208 SET_USR_FIELD(USR_OVF, 1);
1210 gen_set_label(ret_label);
1213 #include "tcg_funcs_generated.c.inc"
1214 #include "tcg_func_table_generated.c.inc"