xref: /openbmc/qemu/target/hexagon/genptr.c (revision 71ed3697)
157acfcdeSTaylor Simpson /*
25ef5fdbaSTaylor Simpson  *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
357acfcdeSTaylor Simpson  *
457acfcdeSTaylor Simpson  *  This program is free software; you can redistribute it and/or modify
557acfcdeSTaylor Simpson  *  it under the terms of the GNU General Public License as published by
657acfcdeSTaylor Simpson  *  the Free Software Foundation; either version 2 of the License, or
757acfcdeSTaylor Simpson  *  (at your option) any later version.
857acfcdeSTaylor Simpson  *
957acfcdeSTaylor Simpson  *  This program is distributed in the hope that it will be useful,
1057acfcdeSTaylor Simpson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1157acfcdeSTaylor Simpson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1257acfcdeSTaylor Simpson  *  GNU General Public License for more details.
1357acfcdeSTaylor Simpson  *
1457acfcdeSTaylor Simpson  *  You should have received a copy of the GNU General Public License
1557acfcdeSTaylor Simpson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1657acfcdeSTaylor Simpson  */
1757acfcdeSTaylor Simpson 
1857acfcdeSTaylor Simpson #include "qemu/osdep.h"
1957acfcdeSTaylor Simpson #include "cpu.h"
2057acfcdeSTaylor Simpson #include "internal.h"
2157acfcdeSTaylor Simpson #include "tcg/tcg-op.h"
22887d61b2STaylor Simpson #include "tcg/tcg-op-gvec.h"
2357acfcdeSTaylor Simpson #include "insn.h"
2457acfcdeSTaylor Simpson #include "opcodes.h"
2557acfcdeSTaylor Simpson #include "translate.h"
26a33872ebSTaylor Simpson #define QEMU_GENERATE       /* Used internally by macros.h */
2757acfcdeSTaylor Simpson #include "macros.h"
28887d61b2STaylor Simpson #include "mmvec/macros.h"
29a33872ebSTaylor Simpson #undef QEMU_GENERATE
3057acfcdeSTaylor Simpson #include "gen_tcg.h"
31d51bcabeSTaylor Simpson #include "gen_tcg_hvx.h"
327e8b3b39SPaolo Montesel #include "genptr.h"
337e8b3b39SPaolo Montesel 
3442659e04SNiccolò Izzo TCGv gen_read_reg(TCGv result, int num)
3542659e04SNiccolò Izzo {
3642659e04SNiccolò Izzo     tcg_gen_mov_tl(result, hex_gpr[num]);
3742659e04SNiccolò Izzo     return result;
3842659e04SNiccolò Izzo }
3942659e04SNiccolò Izzo 
407e8b3b39SPaolo Montesel TCGv gen_read_preg(TCGv pred, uint8_t num)
417e8b3b39SPaolo Montesel {
427e8b3b39SPaolo Montesel     tcg_gen_mov_tl(pred, hex_pred[num]);
437e8b3b39SPaolo Montesel     return pred;
447e8b3b39SPaolo Montesel }
4557acfcdeSTaylor Simpson 
46d63aeb3bSMarco Liebel #define IMMUTABLE (~0)
47d63aeb3bSMarco Liebel 
48d63aeb3bSMarco Liebel static const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = {
49d63aeb3bSMarco Liebel     [HEX_REG_USR] = 0xc13000c0,
50d63aeb3bSMarco Liebel     [HEX_REG_PC] = IMMUTABLE,
51d63aeb3bSMarco Liebel     [HEX_REG_GP] = 0x3f,
52d63aeb3bSMarco Liebel     [HEX_REG_UPCYCLELO] = IMMUTABLE,
53d63aeb3bSMarco Liebel     [HEX_REG_UPCYCLEHI] = IMMUTABLE,
54d63aeb3bSMarco Liebel     [HEX_REG_UTIMERLO] = IMMUTABLE,
55d63aeb3bSMarco Liebel     [HEX_REG_UTIMERHI] = IMMUTABLE,
56d63aeb3bSMarco Liebel };
57d63aeb3bSMarco Liebel 
58d63aeb3bSMarco Liebel static inline void gen_masked_reg_write(TCGv new_val, TCGv cur_val,
59d63aeb3bSMarco Liebel                                         target_ulong reg_mask)
60d63aeb3bSMarco Liebel {
61d63aeb3bSMarco Liebel     if (reg_mask) {
62d63aeb3bSMarco Liebel         TCGv tmp = tcg_temp_new();
63d63aeb3bSMarco Liebel 
64d63aeb3bSMarco Liebel         /* new_val = (new_val & ~reg_mask) | (cur_val & reg_mask) */
65d63aeb3bSMarco Liebel         tcg_gen_andi_tl(new_val, new_val, ~reg_mask);
66d63aeb3bSMarco Liebel         tcg_gen_andi_tl(tmp, cur_val, reg_mask);
67d63aeb3bSMarco Liebel         tcg_gen_or_tl(new_val, new_val, tmp);
68d63aeb3bSMarco Liebel     }
69d63aeb3bSMarco Liebel }
70d63aeb3bSMarco Liebel 
71e28b77a6STaylor Simpson static TCGv get_result_gpr(DisasContext *ctx, int rnum)
7257acfcdeSTaylor Simpson {
73e28b77a6STaylor Simpson     return hex_new_value[rnum];
7485580a65STaylor Simpson }
75e28b77a6STaylor Simpson 
76e28b77a6STaylor Simpson static TCGv_i64 get_result_gpr_pair(DisasContext *ctx, int rnum)
77e28b77a6STaylor Simpson {
78e28b77a6STaylor Simpson     TCGv_i64 result = tcg_temp_new_i64();
79e28b77a6STaylor Simpson     tcg_gen_concat_i32_i64(result, hex_new_value[rnum],
80e28b77a6STaylor Simpson                                    hex_new_value[rnum + 1]);
81e28b77a6STaylor Simpson     return result;
8257acfcdeSTaylor Simpson }
8357acfcdeSTaylor Simpson 
8407540a28STaylor Simpson void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val)
8557acfcdeSTaylor Simpson {
86d63aeb3bSMarco Liebel     const target_ulong reg_mask = reg_immut_masks[rnum];
87d63aeb3bSMarco Liebel 
88d63aeb3bSMarco Liebel     gen_masked_reg_write(val, hex_gpr[rnum], reg_mask);
8957acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_new_value[rnum], val);
9085580a65STaylor Simpson     if (HEX_DEBUG) {
9157acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
9257acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum], 1);
9385580a65STaylor Simpson     }
9457acfcdeSTaylor Simpson }
9557acfcdeSTaylor Simpson 
9607540a28STaylor Simpson static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
9757acfcdeSTaylor Simpson {
98d63aeb3bSMarco Liebel     const target_ulong reg_mask_low = reg_immut_masks[rnum];
99d63aeb3bSMarco Liebel     const target_ulong reg_mask_high = reg_immut_masks[rnum + 1];
100d63aeb3bSMarco Liebel     TCGv val32 = tcg_temp_new();
101d63aeb3bSMarco Liebel 
10257acfcdeSTaylor Simpson     /* Low word */
103d63aeb3bSMarco Liebel     tcg_gen_extrl_i64_i32(val32, val);
104d63aeb3bSMarco Liebel     gen_masked_reg_write(val32, hex_gpr[rnum], reg_mask_low);
105d63aeb3bSMarco Liebel     tcg_gen_mov_tl(hex_new_value[rnum], val32);
10685580a65STaylor Simpson     if (HEX_DEBUG) {
10757acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
10857acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum], 1);
10985580a65STaylor Simpson     }
11057acfcdeSTaylor Simpson 
11157acfcdeSTaylor Simpson     /* High word */
112d63aeb3bSMarco Liebel     tcg_gen_extrh_i64_i32(val32, val);
113d63aeb3bSMarco Liebel     gen_masked_reg_write(val32, hex_gpr[rnum + 1], reg_mask_high);
114d63aeb3bSMarco Liebel     tcg_gen_mov_tl(hex_new_value[rnum + 1], val32);
11585580a65STaylor Simpson     if (HEX_DEBUG) {
11657acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
11757acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1);
11885580a65STaylor Simpson     }
11957acfcdeSTaylor Simpson }
12057acfcdeSTaylor Simpson 
1217e8b3b39SPaolo Montesel void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
12257acfcdeSTaylor Simpson {
12357acfcdeSTaylor Simpson     TCGv base_val = tcg_temp_new();
12457acfcdeSTaylor Simpson 
12557acfcdeSTaylor Simpson     tcg_gen_andi_tl(base_val, val, 0xff);
1266c677c60STaylor Simpson 
1276c677c60STaylor Simpson     /*
1286c677c60STaylor Simpson      * Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual
1296c677c60STaylor Simpson      *
1306c677c60STaylor Simpson      * Multiple writes to the same preg are and'ed together
1316c677c60STaylor Simpson      * If this is the first predicate write in the packet, do a
1326c677c60STaylor Simpson      * straight assignment.  Otherwise, do an and.
1336c677c60STaylor Simpson      */
1346c677c60STaylor Simpson     if (!test_bit(pnum, ctx->pregs_written)) {
1356c677c60STaylor Simpson         tcg_gen_mov_tl(hex_new_pred_value[pnum], base_val);
1366c677c60STaylor Simpson     } else {
1376c677c60STaylor Simpson         tcg_gen_and_tl(hex_new_pred_value[pnum],
1386c677c60STaylor Simpson                        hex_new_pred_value[pnum], base_val);
1396c677c60STaylor Simpson     }
14025e1d87dSTaylor Simpson     if (HEX_DEBUG) {
14157acfcdeSTaylor Simpson         tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
14225e1d87dSTaylor Simpson     }
14310849c26STaylor Simpson     set_bit(pnum, ctx->pregs_written);
14457acfcdeSTaylor Simpson }
14557acfcdeSTaylor Simpson 
14657acfcdeSTaylor Simpson static inline void gen_read_p3_0(TCGv control_reg)
14757acfcdeSTaylor Simpson {
14857acfcdeSTaylor Simpson     tcg_gen_movi_tl(control_reg, 0);
14957acfcdeSTaylor Simpson     for (int i = 0; i < NUM_PREGS; i++) {
15057acfcdeSTaylor Simpson         tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8);
15157acfcdeSTaylor Simpson     }
15257acfcdeSTaylor Simpson }
15357acfcdeSTaylor Simpson 
15457acfcdeSTaylor Simpson /*
15557acfcdeSTaylor Simpson  * Certain control registers require special handling on read
15672895676SMukilan Thiyagarajan  *     HEX_REG_P3_0_ALIASED  aliased to the predicate registers
15757acfcdeSTaylor Simpson  *                           -> concat the 4 predicate registers together
15857acfcdeSTaylor Simpson  *     HEX_REG_PC            actual value stored in DisasContext
15957acfcdeSTaylor Simpson  *                           -> assign from ctx->base.pc_next
16057acfcdeSTaylor Simpson  *     HEX_REG_QEMU_*_CNT    changes in current TB in DisasContext
16157acfcdeSTaylor Simpson  *                           -> add current TB changes to existing reg value
16257acfcdeSTaylor Simpson  */
16357acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
16457acfcdeSTaylor Simpson                                      TCGv dest)
16557acfcdeSTaylor Simpson {
16672895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
16757acfcdeSTaylor Simpson         gen_read_p3_0(dest);
16857acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_PC) {
16957acfcdeSTaylor Simpson         tcg_gen_movi_tl(dest, ctx->base.pc_next);
17057acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
17157acfcdeSTaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT],
17257acfcdeSTaylor Simpson                         ctx->num_packets);
17357acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_INSN_CNT) {
17457acfcdeSTaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT],
17557acfcdeSTaylor Simpson                         ctx->num_insns);
176a82dd548STaylor Simpson     } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
177a82dd548STaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_HVX_CNT],
178a82dd548STaylor Simpson                         ctx->num_hvx_insns);
17957acfcdeSTaylor Simpson     } else {
18057acfcdeSTaylor Simpson         tcg_gen_mov_tl(dest, hex_gpr[reg_num]);
18157acfcdeSTaylor Simpson     }
18257acfcdeSTaylor Simpson }
18357acfcdeSTaylor Simpson 
18457acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
18557acfcdeSTaylor Simpson                                           TCGv_i64 dest)
18657acfcdeSTaylor Simpson {
18772895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
18857acfcdeSTaylor Simpson         TCGv p3_0 = tcg_temp_new();
18957acfcdeSTaylor Simpson         gen_read_p3_0(p3_0);
19057acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
19157acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_PC - 1) {
19223803bbeSPhilippe Mathieu-Daudé         TCGv pc = tcg_constant_tl(ctx->base.pc_next);
19357acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc);
19457acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
19557acfcdeSTaylor Simpson         TCGv pkt_cnt = tcg_temp_new();
19657acfcdeSTaylor Simpson         TCGv insn_cnt = tcg_temp_new();
19757acfcdeSTaylor Simpson         tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT],
19857acfcdeSTaylor Simpson                         ctx->num_packets);
19957acfcdeSTaylor Simpson         tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT],
20057acfcdeSTaylor Simpson                         ctx->num_insns);
20157acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt);
202a82dd548STaylor Simpson     } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
203a82dd548STaylor Simpson         TCGv hvx_cnt = tcg_temp_new();
204a82dd548STaylor Simpson         tcg_gen_addi_tl(hvx_cnt, hex_gpr[HEX_REG_QEMU_HVX_CNT],
205a82dd548STaylor Simpson                         ctx->num_hvx_insns);
206a82dd548STaylor Simpson         tcg_gen_concat_i32_i64(dest, hvx_cnt, hex_gpr[reg_num + 1]);
20757acfcdeSTaylor Simpson     } else {
20857acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest,
20957acfcdeSTaylor Simpson             hex_gpr[reg_num],
21057acfcdeSTaylor Simpson             hex_gpr[reg_num + 1]);
21157acfcdeSTaylor Simpson     }
21257acfcdeSTaylor Simpson }
21357acfcdeSTaylor Simpson 
214c0d86060STaylor Simpson static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg)
21557acfcdeSTaylor Simpson {
216c0d86060STaylor Simpson     TCGv hex_p8 = tcg_temp_new();
21757acfcdeSTaylor Simpson     for (int i = 0; i < NUM_PREGS; i++) {
218c0d86060STaylor Simpson         tcg_gen_extract_tl(hex_p8, control_reg, i * 8, 8);
219c0d86060STaylor Simpson         gen_log_pred_write(ctx, i, hex_p8);
22057acfcdeSTaylor Simpson     }
22157acfcdeSTaylor Simpson }
22257acfcdeSTaylor Simpson 
22357acfcdeSTaylor Simpson /*
22457acfcdeSTaylor Simpson  * Certain control registers require special handling on write
22572895676SMukilan Thiyagarajan  *     HEX_REG_P3_0_ALIASED  aliased to the predicate registers
22657acfcdeSTaylor Simpson  *                           -> break the value across 4 predicate registers
22757acfcdeSTaylor Simpson  *     HEX_REG_QEMU_*_CNT    changes in current TB in DisasContext
22857acfcdeSTaylor Simpson  *                            -> clear the changes
22957acfcdeSTaylor Simpson  */
23057acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
23157acfcdeSTaylor Simpson                                       TCGv val)
23257acfcdeSTaylor Simpson {
23372895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
234c0d86060STaylor Simpson         gen_write_p3_0(ctx, val);
23557acfcdeSTaylor Simpson     } else {
23607540a28STaylor Simpson         gen_log_reg_write(ctx, reg_num, val);
23757acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_PKT_CNT) {
23857acfcdeSTaylor Simpson             ctx->num_packets = 0;
23957acfcdeSTaylor Simpson         }
24057acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_INSN_CNT) {
24157acfcdeSTaylor Simpson             ctx->num_insns = 0;
24257acfcdeSTaylor Simpson         }
243a82dd548STaylor Simpson         if (reg_num == HEX_REG_QEMU_HVX_CNT) {
244a82dd548STaylor Simpson             ctx->num_hvx_insns = 0;
245a82dd548STaylor Simpson         }
24657acfcdeSTaylor Simpson     }
24757acfcdeSTaylor Simpson }
24857acfcdeSTaylor Simpson 
24957acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
25057acfcdeSTaylor Simpson                                            TCGv_i64 val)
25157acfcdeSTaylor Simpson {
25272895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
253e28b77a6STaylor Simpson         TCGv result = get_result_gpr(ctx, reg_num + 1);
25457acfcdeSTaylor Simpson         TCGv val32 = tcg_temp_new();
25557acfcdeSTaylor Simpson         tcg_gen_extrl_i64_i32(val32, val);
256c0d86060STaylor Simpson         gen_write_p3_0(ctx, val32);
25757acfcdeSTaylor Simpson         tcg_gen_extrh_i64_i32(val32, val);
258e28b77a6STaylor Simpson         tcg_gen_mov_tl(result, val32);
25957acfcdeSTaylor Simpson     } else {
26007540a28STaylor Simpson         gen_log_reg_write_pair(ctx, reg_num, val);
26157acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_PKT_CNT) {
26257acfcdeSTaylor Simpson             ctx->num_packets = 0;
26357acfcdeSTaylor Simpson             ctx->num_insns = 0;
26457acfcdeSTaylor Simpson         }
265a82dd548STaylor Simpson         if (reg_num == HEX_REG_QEMU_HVX_CNT) {
266a82dd548STaylor Simpson             ctx->num_hvx_insns = 0;
267a82dd548STaylor Simpson         }
26857acfcdeSTaylor Simpson     }
26957acfcdeSTaylor Simpson }
27057acfcdeSTaylor Simpson 
2717e8b3b39SPaolo Montesel TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign)
27246ef47e2STaylor Simpson {
27346ef47e2STaylor Simpson     if (sign) {
27446ef47e2STaylor Simpson         tcg_gen_sextract_tl(result, src, N * 8, 8);
27546ef47e2STaylor Simpson     } else {
27646ef47e2STaylor Simpson         tcg_gen_extract_tl(result, src, N * 8, 8);
27746ef47e2STaylor Simpson     }
27846ef47e2STaylor Simpson     return result;
27946ef47e2STaylor Simpson }
28046ef47e2STaylor Simpson 
2817e8b3b39SPaolo Montesel TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign)
2820a65d286STaylor Simpson {
2830a65d286STaylor Simpson     TCGv_i64 res64 = tcg_temp_new_i64();
2840a65d286STaylor Simpson     if (sign) {
2850a65d286STaylor Simpson         tcg_gen_sextract_i64(res64, src, N * 8, 8);
2860a65d286STaylor Simpson     } else {
2870a65d286STaylor Simpson         tcg_gen_extract_i64(res64, src, N * 8, 8);
2880a65d286STaylor Simpson     }
2890a65d286STaylor Simpson     tcg_gen_extrl_i64_i32(result, res64);
2900a65d286STaylor Simpson 
2910a65d286STaylor Simpson     return result;
2920a65d286STaylor Simpson }
2930a65d286STaylor Simpson 
2947e8b3b39SPaolo Montesel TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign)
29546ef47e2STaylor Simpson {
29646ef47e2STaylor Simpson     if (sign) {
29746ef47e2STaylor Simpson         tcg_gen_sextract_tl(result, src, N * 16, 16);
29846ef47e2STaylor Simpson     } else {
29946ef47e2STaylor Simpson         tcg_gen_extract_tl(result, src, N * 16, 16);
30046ef47e2STaylor Simpson     }
30146ef47e2STaylor Simpson     return result;
30246ef47e2STaylor Simpson }
30346ef47e2STaylor Simpson 
3047e8b3b39SPaolo Montesel void gen_set_half(int N, TCGv result, TCGv src)
3050d0b91a8STaylor Simpson {
3060d0b91a8STaylor Simpson     tcg_gen_deposit_tl(result, result, src, N * 16, 16);
3070d0b91a8STaylor Simpson }
3080d0b91a8STaylor Simpson 
3097e8b3b39SPaolo Montesel void gen_set_half_i64(int N, TCGv_i64 result, TCGv src)
3100d0b91a8STaylor Simpson {
3110d0b91a8STaylor Simpson     TCGv_i64 src64 = tcg_temp_new_i64();
3120d0b91a8STaylor Simpson     tcg_gen_extu_i32_i64(src64, src);
3130d0b91a8STaylor Simpson     tcg_gen_deposit_i64(result, result, src64, N * 16, 16);
3140d0b91a8STaylor Simpson }
3150d0b91a8STaylor Simpson 
3167e8b3b39SPaolo Montesel void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src)
3170a65d286STaylor Simpson {
3180a65d286STaylor Simpson     TCGv_i64 src64 = tcg_temp_new_i64();
3190a65d286STaylor Simpson     tcg_gen_extu_i32_i64(src64, src);
3200a65d286STaylor Simpson     tcg_gen_deposit_i64(result, result, src64, N * 8, 8);
3210a65d286STaylor Simpson }
3220a65d286STaylor Simpson 
32357acfcdeSTaylor Simpson static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index)
32457acfcdeSTaylor Simpson {
32553b26d25SRichard Henderson     tcg_gen_qemu_ld_tl(dest, vaddr, mem_index, MO_TEUL);
32657acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_addr, vaddr);
32757acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_val, dest);
32857acfcdeSTaylor Simpson }
32957acfcdeSTaylor Simpson 
33057acfcdeSTaylor Simpson static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index)
33157acfcdeSTaylor Simpson {
33253b26d25SRichard Henderson     tcg_gen_qemu_ld_i64(dest, vaddr, mem_index, MO_TEUQ);
33357acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_addr, vaddr);
33457acfcdeSTaylor Simpson     tcg_gen_mov_i64(hex_llsc_val_i64, dest);
33557acfcdeSTaylor Simpson }
33657acfcdeSTaylor Simpson 
33788725336STaylor Simpson static inline void gen_store_conditional4(DisasContext *ctx,
33857acfcdeSTaylor Simpson                                           TCGv pred, TCGv vaddr, TCGv src)
33957acfcdeSTaylor Simpson {
34057acfcdeSTaylor Simpson     TCGLabel *fail = gen_new_label();
34157acfcdeSTaylor Simpson     TCGLabel *done = gen_new_label();
34257acfcdeSTaylor Simpson     TCGv one, zero, tmp;
34357acfcdeSTaylor Simpson 
34457acfcdeSTaylor Simpson     tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
34557acfcdeSTaylor Simpson 
34623803bbeSPhilippe Mathieu-Daudé     one = tcg_constant_tl(0xff);
34723803bbeSPhilippe Mathieu-Daudé     zero = tcg_constant_tl(0);
34857acfcdeSTaylor Simpson     tmp = tcg_temp_new();
34957acfcdeSTaylor Simpson     tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src,
35057acfcdeSTaylor Simpson                               ctx->mem_idx, MO_32);
35188725336STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, pred, tmp, hex_llsc_val,
35257acfcdeSTaylor Simpson                        one, zero);
35357acfcdeSTaylor Simpson     tcg_gen_br(done);
35457acfcdeSTaylor Simpson 
35557acfcdeSTaylor Simpson     gen_set_label(fail);
35657acfcdeSTaylor Simpson     tcg_gen_movi_tl(pred, 0);
35757acfcdeSTaylor Simpson 
35857acfcdeSTaylor Simpson     gen_set_label(done);
35957acfcdeSTaylor Simpson     tcg_gen_movi_tl(hex_llsc_addr, ~0);
36057acfcdeSTaylor Simpson }
36157acfcdeSTaylor Simpson 
36288725336STaylor Simpson static inline void gen_store_conditional8(DisasContext *ctx,
36357acfcdeSTaylor Simpson                                           TCGv pred, TCGv vaddr, TCGv_i64 src)
36457acfcdeSTaylor Simpson {
36557acfcdeSTaylor Simpson     TCGLabel *fail = gen_new_label();
36657acfcdeSTaylor Simpson     TCGLabel *done = gen_new_label();
36757acfcdeSTaylor Simpson     TCGv_i64 one, zero, tmp;
36857acfcdeSTaylor Simpson 
36957acfcdeSTaylor Simpson     tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
37057acfcdeSTaylor Simpson 
37123803bbeSPhilippe Mathieu-Daudé     one = tcg_constant_i64(0xff);
37223803bbeSPhilippe Mathieu-Daudé     zero = tcg_constant_i64(0);
37357acfcdeSTaylor Simpson     tmp = tcg_temp_new_i64();
37457acfcdeSTaylor Simpson     tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src,
37557acfcdeSTaylor Simpson                                ctx->mem_idx, MO_64);
37657acfcdeSTaylor Simpson     tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64,
37757acfcdeSTaylor Simpson                         one, zero);
37888725336STaylor Simpson     tcg_gen_extrl_i64_i32(pred, tmp);
37957acfcdeSTaylor Simpson     tcg_gen_br(done);
38057acfcdeSTaylor Simpson 
38157acfcdeSTaylor Simpson     gen_set_label(fail);
38257acfcdeSTaylor Simpson     tcg_gen_movi_tl(pred, 0);
38357acfcdeSTaylor Simpson 
38457acfcdeSTaylor Simpson     gen_set_label(done);
38557acfcdeSTaylor Simpson     tcg_gen_movi_tl(hex_llsc_addr, ~0);
38657acfcdeSTaylor Simpson }
38757acfcdeSTaylor Simpson 
3887e8b3b39SPaolo Montesel void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot)
38946ef47e2STaylor Simpson {
39046ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
39146ef47e2STaylor Simpson     tcg_gen_movi_tl(hex_store_width[slot], width);
39246ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_val32[slot], src);
39346ef47e2STaylor Simpson }
39446ef47e2STaylor Simpson 
3957e8b3b39SPaolo Montesel void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
39646ef47e2STaylor Simpson {
39746ef47e2STaylor Simpson     gen_store32(vaddr, src, 1, slot);
39846ef47e2STaylor Simpson }
39946ef47e2STaylor Simpson 
4007e8b3b39SPaolo Montesel void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot)
40146ef47e2STaylor Simpson {
40223803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
403661ad999STaylor Simpson     gen_store1(cpu_env, vaddr, tmp, slot);
40446ef47e2STaylor Simpson }
40546ef47e2STaylor Simpson 
4067e8b3b39SPaolo Montesel void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
40746ef47e2STaylor Simpson {
40846ef47e2STaylor Simpson     gen_store32(vaddr, src, 2, slot);
40946ef47e2STaylor Simpson }
41046ef47e2STaylor Simpson 
4117e8b3b39SPaolo Montesel void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot)
41246ef47e2STaylor Simpson {
41323803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
414661ad999STaylor Simpson     gen_store2(cpu_env, vaddr, tmp, slot);
41546ef47e2STaylor Simpson }
41646ef47e2STaylor Simpson 
4177e8b3b39SPaolo Montesel void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
41846ef47e2STaylor Simpson {
41946ef47e2STaylor Simpson     gen_store32(vaddr, src, 4, slot);
42046ef47e2STaylor Simpson }
42146ef47e2STaylor Simpson 
4227e8b3b39SPaolo Montesel void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot)
42346ef47e2STaylor Simpson {
42423803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
425661ad999STaylor Simpson     gen_store4(cpu_env, vaddr, tmp, slot);
42646ef47e2STaylor Simpson }
42746ef47e2STaylor Simpson 
4287e8b3b39SPaolo Montesel void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, uint32_t slot)
42946ef47e2STaylor Simpson {
43046ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
43146ef47e2STaylor Simpson     tcg_gen_movi_tl(hex_store_width[slot], 8);
43246ef47e2STaylor Simpson     tcg_gen_mov_i64(hex_store_val64[slot], src);
43346ef47e2STaylor Simpson }
43446ef47e2STaylor Simpson 
4357e8b3b39SPaolo Montesel void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, uint32_t slot)
43646ef47e2STaylor Simpson {
43723803bbeSPhilippe Mathieu-Daudé     TCGv_i64 tmp = tcg_constant_i64(src);
438661ad999STaylor Simpson     gen_store8(cpu_env, vaddr, tmp, slot);
43946ef47e2STaylor Simpson }
44046ef47e2STaylor Simpson 
4417e8b3b39SPaolo Montesel TCGv gen_8bitsof(TCGv result, TCGv value)
44257d352acSTaylor Simpson {
44323803bbeSPhilippe Mathieu-Daudé     TCGv zero = tcg_constant_tl(0);
44423803bbeSPhilippe Mathieu-Daudé     TCGv ones = tcg_constant_tl(0xff);
44557d352acSTaylor Simpson     tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero);
44657d352acSTaylor Simpson 
44757d352acSTaylor Simpson     return result;
44857d352acSTaylor Simpson }
44957d352acSTaylor Simpson 
45061c6c06eSTaylor Simpson static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
45161c6c06eSTaylor Simpson                                   TCGCond cond, TCGv pred)
45261c6c06eSTaylor Simpson {
45361c6c06eSTaylor Simpson     TCGLabel *pred_false = NULL;
45461c6c06eSTaylor Simpson     if (cond != TCG_COND_ALWAYS) {
45561c6c06eSTaylor Simpson         pred_false = gen_new_label();
45661c6c06eSTaylor Simpson         tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
45761c6c06eSTaylor Simpson     }
45861c6c06eSTaylor Simpson 
45961c6c06eSTaylor Simpson     if (ctx->pkt->pkt_has_multi_cof) {
46061c6c06eSTaylor Simpson         /* If there are multiple branches in a packet, ignore the second one */
46161c6c06eSTaylor Simpson         tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
46261c6c06eSTaylor Simpson                            hex_branch_taken, tcg_constant_tl(0),
46361c6c06eSTaylor Simpson                            hex_gpr[HEX_REG_PC], addr);
46461c6c06eSTaylor Simpson         tcg_gen_movi_tl(hex_branch_taken, 1);
46561c6c06eSTaylor Simpson     } else {
46661c6c06eSTaylor Simpson         tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
46761c6c06eSTaylor Simpson     }
46861c6c06eSTaylor Simpson 
46961c6c06eSTaylor Simpson     if (cond != TCG_COND_ALWAYS) {
47061c6c06eSTaylor Simpson         gen_set_label(pred_false);
47161c6c06eSTaylor Simpson     }
47261c6c06eSTaylor Simpson }
47361c6c06eSTaylor Simpson 
47461c6c06eSTaylor Simpson static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
47561c6c06eSTaylor Simpson                                    TCGCond cond, TCGv pred)
47661c6c06eSTaylor Simpson {
47761c6c06eSTaylor Simpson     target_ulong dest = ctx->pkt->pc + pc_off;
4781b9a7f2aSTaylor Simpson     if (ctx->pkt->pkt_has_multi_cof) {
47961c6c06eSTaylor Simpson         gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
4801b9a7f2aSTaylor Simpson     } else {
4811b9a7f2aSTaylor Simpson         /* Defer this jump to the end of the TB */
4821b9a7f2aSTaylor Simpson         ctx->branch_cond = TCG_COND_ALWAYS;
4831b9a7f2aSTaylor Simpson         if (pred != NULL) {
4841b9a7f2aSTaylor Simpson             ctx->branch_cond = cond;
4851b9a7f2aSTaylor Simpson             tcg_gen_mov_tl(hex_branch_taken, pred);
4861b9a7f2aSTaylor Simpson         }
4871b9a7f2aSTaylor Simpson         ctx->branch_dest = dest;
4881b9a7f2aSTaylor Simpson     }
48961c6c06eSTaylor Simpson }
49061c6c06eSTaylor Simpson 
491148ef7fdSTaylor Simpson void gen_set_usr_field(DisasContext *ctx, int field, TCGv val)
492564b2040STaylor Simpson {
493148ef7fdSTaylor Simpson     TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
494148ef7fdSTaylor Simpson     tcg_gen_deposit_tl(usr, usr, val,
495564b2040STaylor Simpson                        reg_field_info[field].offset,
496564b2040STaylor Simpson                        reg_field_info[field].width);
497564b2040STaylor Simpson }
498564b2040STaylor Simpson 
499148ef7fdSTaylor Simpson void gen_set_usr_fieldi(DisasContext *ctx, int field, int x)
500564b2040STaylor Simpson {
501564b2040STaylor Simpson     if (reg_field_info[field].width == 1) {
502148ef7fdSTaylor Simpson         TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
503564b2040STaylor Simpson         target_ulong bit = 1 << reg_field_info[field].offset;
504564b2040STaylor Simpson         if ((x & 1) == 1) {
505148ef7fdSTaylor Simpson             tcg_gen_ori_tl(usr, usr, bit);
506564b2040STaylor Simpson         } else {
507148ef7fdSTaylor Simpson             tcg_gen_andi_tl(usr, usr, ~bit);
508564b2040STaylor Simpson         }
509564b2040STaylor Simpson     } else {
510564b2040STaylor Simpson         TCGv val = tcg_constant_tl(x);
511148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, field, val);
512564b2040STaylor Simpson     }
513564b2040STaylor Simpson }
514564b2040STaylor Simpson 
51511b577ffSTaylor Simpson static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
51611b577ffSTaylor Simpson {
51711b577ffSTaylor Simpson     TCGv one = tcg_constant_tl(0xff);
51811b577ffSTaylor Simpson     TCGv zero = tcg_constant_tl(0);
51911b577ffSTaylor Simpson 
52011b577ffSTaylor Simpson     tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
52111b577ffSTaylor Simpson }
52211b577ffSTaylor Simpson 
52317fda3c2STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
52417fda3c2STaylor Simpson static inline void gen_loop0r(DisasContext *ctx, TCGv RsV, int riV)
52517fda3c2STaylor Simpson {
52617fda3c2STaylor Simpson     fIMMEXT(riV);
52717fda3c2STaylor Simpson     fPCALIGN(riV);
52817fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_LC0, RsV);
52917fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV));
53017fda3c2STaylor Simpson     gen_set_usr_fieldi(ctx, USR_LPCFG, 0);
53117fda3c2STaylor Simpson }
53217fda3c2STaylor Simpson 
53317fda3c2STaylor Simpson static void gen_loop0i(DisasContext *ctx, int count, int riV)
53417fda3c2STaylor Simpson {
53517fda3c2STaylor Simpson     gen_loop0r(ctx, tcg_constant_tl(count), riV);
53617fda3c2STaylor Simpson }
53717fda3c2STaylor Simpson 
53817fda3c2STaylor Simpson static inline void gen_loop1r(DisasContext *ctx, TCGv RsV, int riV)
53917fda3c2STaylor Simpson {
54017fda3c2STaylor Simpson     fIMMEXT(riV);
54117fda3c2STaylor Simpson     fPCALIGN(riV);
54217fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_LC1, RsV);
54317fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SA1, tcg_constant_tl(ctx->pkt->pc + riV));
54417fda3c2STaylor Simpson }
54517fda3c2STaylor Simpson 
54617fda3c2STaylor Simpson static void gen_loop1i(DisasContext *ctx, int count, int riV)
54717fda3c2STaylor Simpson {
54817fda3c2STaylor Simpson     gen_loop1r(ctx, tcg_constant_tl(count), riV);
54917fda3c2STaylor Simpson }
55017fda3c2STaylor Simpson 
55117fda3c2STaylor Simpson static void gen_ploopNsr(DisasContext *ctx, int N, TCGv RsV, int riV)
55217fda3c2STaylor Simpson {
55317fda3c2STaylor Simpson     fIMMEXT(riV);
55417fda3c2STaylor Simpson     fPCALIGN(riV);
55517fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_LC0, RsV);
55617fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV));
55717fda3c2STaylor Simpson     gen_set_usr_fieldi(ctx, USR_LPCFG, N);
55817fda3c2STaylor Simpson     gen_log_pred_write(ctx, 3, tcg_constant_tl(0));
55917fda3c2STaylor Simpson }
56017fda3c2STaylor Simpson 
56117fda3c2STaylor Simpson static void gen_ploopNsi(DisasContext *ctx, int N, int count, int riV)
56217fda3c2STaylor Simpson {
56317fda3c2STaylor Simpson     gen_ploopNsr(ctx, N, tcg_constant_tl(count), riV);
56417fda3c2STaylor Simpson }
565d24f0b2bSTaylor Simpson 
566d24f0b2bSTaylor Simpson static inline void gen_comparei(TCGCond cond, TCGv res, TCGv arg1, int arg2)
567d24f0b2bSTaylor Simpson {
568d24f0b2bSTaylor Simpson     gen_compare(cond, res, arg1, tcg_constant_tl(arg2));
569d24f0b2bSTaylor Simpson }
57017fda3c2STaylor Simpson #endif
57117fda3c2STaylor Simpson 
57297b16fafSTaylor Simpson static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
57397b16fafSTaylor Simpson                            TCGCond cond, TCGv pred)
57497b16fafSTaylor Simpson {
57597b16fafSTaylor Simpson     gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
57697b16fafSTaylor Simpson }
57797b16fafSTaylor Simpson 
5785ef5fdbaSTaylor Simpson static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred)
5795ef5fdbaSTaylor Simpson {
5805ef5fdbaSTaylor Simpson     TCGv LSB = tcg_temp_new();
5815ef5fdbaSTaylor Simpson     tcg_gen_andi_tl(LSB, pred, 1);
5825ef5fdbaSTaylor Simpson     gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB);
5835ef5fdbaSTaylor Simpson }
5845ef5fdbaSTaylor Simpson 
58511b577ffSTaylor Simpson static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
58611b577ffSTaylor Simpson                           int pc_off)
58711b577ffSTaylor Simpson {
58811b577ffSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
58911b577ffSTaylor Simpson }
59011b577ffSTaylor Simpson 
59111b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp(DisasContext *ctx,
59211b577ffSTaylor Simpson                               int pnum, TCGCond cond1, TCGv arg1, TCGv arg2,
59311b577ffSTaylor Simpson                               TCGCond cond2, int pc_off)
59411b577ffSTaylor Simpson {
59511b577ffSTaylor Simpson     if (ctx->insn->part1) {
59611b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
59711b577ffSTaylor Simpson         gen_compare(cond1, pred, arg1, arg2);
59811b577ffSTaylor Simpson         gen_log_pred_write(ctx, pnum, pred);
59911b577ffSTaylor Simpson     } else {
60011b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
60111b577ffSTaylor Simpson         tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
60211b577ffSTaylor Simpson         gen_cond_jump(ctx, cond2, pred, pc_off);
60311b577ffSTaylor Simpson     }
60411b577ffSTaylor Simpson }
60511b577ffSTaylor Simpson 
60611b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
60711b577ffSTaylor Simpson                                 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
60811b577ffSTaylor Simpson                                 int pc_off)
60911b577ffSTaylor Simpson {
61011b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
61111b577ffSTaylor Simpson }
61211b577ffSTaylor Simpson 
61311b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
61411b577ffSTaylor Simpson                                 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
61511b577ffSTaylor Simpson                                 int pc_off)
61611b577ffSTaylor Simpson {
61711b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
61811b577ffSTaylor Simpson }
61911b577ffSTaylor Simpson 
62011b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
62111b577ffSTaylor Simpson                                  int pnum, TCGCond cond, TCGv arg1, int arg2,
62211b577ffSTaylor Simpson                                  int pc_off)
62311b577ffSTaylor Simpson {
62411b577ffSTaylor Simpson     TCGv tmp = tcg_constant_tl(arg2);
62511b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
62611b577ffSTaylor Simpson }
62711b577ffSTaylor Simpson 
62811b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
62911b577ffSTaylor Simpson                                  int pnum, TCGCond cond, TCGv arg1, int arg2,
63011b577ffSTaylor Simpson                                  int pc_off)
63111b577ffSTaylor Simpson {
63211b577ffSTaylor Simpson     TCGv tmp = tcg_constant_tl(arg2);
63311b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
63411b577ffSTaylor Simpson }
63511b577ffSTaylor Simpson 
63611b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
63711b577ffSTaylor Simpson                                    TCGv arg, int pc_off)
63811b577ffSTaylor Simpson {
63911b577ffSTaylor Simpson     gen_cmpnd_cmpi_jmp_t(ctx, pnum, cond, arg, -1, pc_off);
64011b577ffSTaylor Simpson }
64111b577ffSTaylor Simpson 
64211b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_f(DisasContext *ctx, int pnum, TCGCond cond,
64311b577ffSTaylor Simpson                                    TCGv arg, int pc_off)
64411b577ffSTaylor Simpson {
64511b577ffSTaylor Simpson     gen_cmpnd_cmpi_jmp_f(ctx, pnum, cond, arg, -1, pc_off);
64611b577ffSTaylor Simpson }
64711b577ffSTaylor Simpson 
64811b577ffSTaylor Simpson static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
64911b577ffSTaylor Simpson                                   int pnum, TCGv arg, TCGCond cond, int pc_off)
65011b577ffSTaylor Simpson {
65111b577ffSTaylor Simpson     if (ctx->insn->part1) {
65211b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
65311b577ffSTaylor Simpson         tcg_gen_andi_tl(pred, arg, 1);
65411b577ffSTaylor Simpson         gen_8bitsof(pred, pred);
65511b577ffSTaylor Simpson         gen_log_pred_write(ctx, pnum, pred);
65611b577ffSTaylor Simpson     } else {
65711b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
65811b577ffSTaylor Simpson         tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
65911b577ffSTaylor Simpson         gen_cond_jump(ctx, cond, pred, pc_off);
66011b577ffSTaylor Simpson     }
66111b577ffSTaylor Simpson }
66211b577ffSTaylor Simpson 
66397b16fafSTaylor Simpson static void gen_testbit0_jumpnv(DisasContext *ctx,
66497b16fafSTaylor Simpson                                 TCGv arg, TCGCond cond, int pc_off)
66597b16fafSTaylor Simpson {
66697b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
66797b16fafSTaylor Simpson     tcg_gen_andi_tl(pred, arg, 1);
66897b16fafSTaylor Simpson     gen_cond_jump(ctx, cond, pred, pc_off);
66997b16fafSTaylor Simpson }
67097b16fafSTaylor Simpson 
67197b16fafSTaylor Simpson static void gen_jump(DisasContext *ctx, int pc_off)
67297b16fafSTaylor Simpson {
67397b16fafSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
67497b16fafSTaylor Simpson }
67597b16fafSTaylor Simpson 
67697b16fafSTaylor Simpson static void gen_jumpr(DisasContext *ctx, TCGv new_pc)
67797b16fafSTaylor Simpson {
67897b16fafSTaylor Simpson     gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
67997b16fafSTaylor Simpson }
68097b16fafSTaylor Simpson 
68161c6c06eSTaylor Simpson static void gen_call(DisasContext *ctx, int pc_off)
68261c6c06eSTaylor Simpson {
683e28b77a6STaylor Simpson     TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
684e28b77a6STaylor Simpson     tcg_gen_movi_tl(lr, ctx->next_PC);
68561c6c06eSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
68661c6c06eSTaylor Simpson }
68761c6c06eSTaylor Simpson 
688242af2c0STaylor Simpson static void gen_callr(DisasContext *ctx, TCGv new_pc)
689242af2c0STaylor Simpson {
690e28b77a6STaylor Simpson     TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
691e28b77a6STaylor Simpson     tcg_gen_movi_tl(lr, ctx->next_PC);
692242af2c0STaylor Simpson     gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
693242af2c0STaylor Simpson }
694242af2c0STaylor Simpson 
69561c6c06eSTaylor Simpson static void gen_cond_call(DisasContext *ctx, TCGv pred,
69661c6c06eSTaylor Simpson                           TCGCond cond, int pc_off)
69761c6c06eSTaylor Simpson {
698e28b77a6STaylor Simpson     TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
6997a819de8SRichard Henderson     TCGv lsb = tcg_temp_new();
70061c6c06eSTaylor Simpson     TCGLabel *skip = gen_new_label();
70161c6c06eSTaylor Simpson     tcg_gen_andi_tl(lsb, pred, 1);
70261c6c06eSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
70361c6c06eSTaylor Simpson     tcg_gen_brcondi_tl(cond, lsb, 0, skip);
704e28b77a6STaylor Simpson     tcg_gen_movi_tl(lr, ctx->next_PC);
70561c6c06eSTaylor Simpson     gen_set_label(skip);
70661c6c06eSTaylor Simpson }
70761c6c06eSTaylor Simpson 
708242af2c0STaylor Simpson static void gen_cond_callr(DisasContext *ctx,
709242af2c0STaylor Simpson                            TCGCond cond, TCGv pred, TCGv new_pc)
710242af2c0STaylor Simpson {
711242af2c0STaylor Simpson     TCGv lsb = tcg_temp_new();
712242af2c0STaylor Simpson     TCGLabel *skip = gen_new_label();
713242af2c0STaylor Simpson     tcg_gen_andi_tl(lsb, pred, 1);
714242af2c0STaylor Simpson     tcg_gen_brcondi_tl(cond, lsb, 0, skip);
715242af2c0STaylor Simpson     gen_callr(ctx, new_pc);
716242af2c0STaylor Simpson     gen_set_label(skip);
717242af2c0STaylor Simpson }
718242af2c0STaylor Simpson 
719085b6700STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
720085b6700STaylor Simpson /* frame = ((LR << 32) | FP) ^ (FRAMEKEY << 32)) */
721085b6700STaylor Simpson static TCGv_i64 gen_frame_scramble(void)
722085b6700STaylor Simpson {
723085b6700STaylor Simpson     TCGv_i64 frame = tcg_temp_new_i64();
724085b6700STaylor Simpson     TCGv tmp = tcg_temp_new();
725085b6700STaylor Simpson     tcg_gen_xor_tl(tmp, hex_gpr[HEX_REG_LR], hex_gpr[HEX_REG_FRAMEKEY]);
726085b6700STaylor Simpson     tcg_gen_concat_i32_i64(frame, hex_gpr[HEX_REG_FP], tmp);
727085b6700STaylor Simpson     return frame;
728085b6700STaylor Simpson }
729085b6700STaylor Simpson #endif
730085b6700STaylor Simpson 
731dae386b8STaylor Simpson /* frame ^= (int64_t)FRAMEKEY << 32 */
732dae386b8STaylor Simpson static void gen_frame_unscramble(TCGv_i64 frame)
733dae386b8STaylor Simpson {
734dae386b8STaylor Simpson     TCGv_i64 framekey = tcg_temp_new_i64();
735dae386b8STaylor Simpson     tcg_gen_extu_i32_i64(framekey, hex_gpr[HEX_REG_FRAMEKEY]);
736dae386b8STaylor Simpson     tcg_gen_shli_i64(framekey, framekey, 32);
737dae386b8STaylor Simpson     tcg_gen_xor_i64(frame, frame, framekey);
738dae386b8STaylor Simpson }
739dae386b8STaylor Simpson 
740dae386b8STaylor Simpson static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
741dae386b8STaylor Simpson {
742dae386b8STaylor Simpson     Insn *insn = ctx->insn;  /* Needed for CHECK_NOSHUF */
743dae386b8STaylor Simpson     CHECK_NOSHUF(EA, 8);
74453b26d25SRichard Henderson     tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ);
745dae386b8STaylor Simpson }
746dae386b8STaylor Simpson 
747085b6700STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
748085b6700STaylor Simpson /* Stack overflow check */
749085b6700STaylor Simpson static void gen_framecheck(TCGv EA, int framesize)
750085b6700STaylor Simpson {
751085b6700STaylor Simpson     /* Not modelled in linux-user mode */
752085b6700STaylor Simpson     /* Placeholder for system mode */
753085b6700STaylor Simpson #ifndef CONFIG_USER_ONLY
754085b6700STaylor Simpson     g_assert_not_reached();
755085b6700STaylor Simpson #endif
756085b6700STaylor Simpson }
757085b6700STaylor Simpson 
758085b6700STaylor Simpson static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize)
759085b6700STaylor Simpson {
760085b6700STaylor Simpson     TCGv r30 = tcg_temp_new();
761085b6700STaylor Simpson     TCGv_i64 frame;
762085b6700STaylor Simpson     tcg_gen_addi_tl(r30, r29, -8);
763085b6700STaylor Simpson     frame = gen_frame_scramble();
764085b6700STaylor Simpson     gen_store8(cpu_env, r30, frame, ctx->insn->slot);
765085b6700STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_FP, r30);
766085b6700STaylor Simpson     gen_framecheck(r30, framesize);
767085b6700STaylor Simpson     tcg_gen_subi_tl(r29, r30, framesize);
768085b6700STaylor Simpson }
769085b6700STaylor Simpson 
770085b6700STaylor Simpson static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30)
771085b6700STaylor Simpson {
772085b6700STaylor Simpson     TCGv r29 = tcg_temp_new();
773085b6700STaylor Simpson     TCGv_i64 frame = tcg_temp_new_i64();
774085b6700STaylor Simpson     gen_load_frame(ctx, frame, r30);
775085b6700STaylor Simpson     gen_frame_unscramble(frame);
776085b6700STaylor Simpson     tcg_gen_mov_i64(r31_30, frame);
777085b6700STaylor Simpson     tcg_gen_addi_tl(r29, r30, 8);
778085b6700STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SP, r29);
779085b6700STaylor Simpson }
780085b6700STaylor Simpson #endif
781085b6700STaylor Simpson 
782e28b77a6STaylor Simpson static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
783dae386b8STaylor Simpson {
784dae386b8STaylor Simpson     /*
785dae386b8STaylor Simpson      * frame = *src
786dae386b8STaylor Simpson      * dst = frame_unscramble(frame)
787dae386b8STaylor Simpson      * SP = src + 8
788dae386b8STaylor Simpson      * PC = dst.w[1]
789dae386b8STaylor Simpson      */
790dae386b8STaylor Simpson     TCGv_i64 frame = tcg_temp_new_i64();
791dae386b8STaylor Simpson     TCGv r31 = tcg_temp_new();
792e28b77a6STaylor Simpson     TCGv r29 = get_result_gpr(ctx, HEX_REG_SP);
793dae386b8STaylor Simpson 
794dae386b8STaylor Simpson     gen_load_frame(ctx, frame, src);
795dae386b8STaylor Simpson     gen_frame_unscramble(frame);
796dae386b8STaylor Simpson     tcg_gen_mov_i64(dst, frame);
797dae386b8STaylor Simpson     tcg_gen_addi_tl(r29, src, 8);
798dae386b8STaylor Simpson     tcg_gen_extrh_i64_i32(r31, dst);
799dae386b8STaylor Simpson     gen_jumpr(ctx, r31);
800dae386b8STaylor Simpson }
801dae386b8STaylor Simpson 
802dae386b8STaylor Simpson /* if (pred) dst = dealloc_return(src):raw */
803dae386b8STaylor Simpson static void gen_cond_return(DisasContext *ctx, TCGv_i64 dst, TCGv src,
804dae386b8STaylor Simpson                             TCGv pred, TCGCond cond)
805dae386b8STaylor Simpson {
806dae386b8STaylor Simpson     TCGv LSB = tcg_temp_new();
807dae386b8STaylor Simpson     TCGLabel *skip = gen_new_label();
808dae386b8STaylor Simpson     tcg_gen_andi_tl(LSB, pred, 1);
809dae386b8STaylor Simpson 
810dae386b8STaylor Simpson     tcg_gen_brcondi_tl(cond, LSB, 0, skip);
811e28b77a6STaylor Simpson     gen_return(ctx, dst, src);
812dae386b8STaylor Simpson     gen_set_label(skip);
813dae386b8STaylor Simpson }
814dae386b8STaylor Simpson 
815dae386b8STaylor Simpson /* sub-instruction version (no RddV, so handle it manually) */
816dae386b8STaylor Simpson static void gen_cond_return_subinsn(DisasContext *ctx, TCGCond cond, TCGv pred)
817dae386b8STaylor Simpson {
818e28b77a6STaylor Simpson     TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP);
819dae386b8STaylor Simpson     gen_cond_return(ctx, RddV, hex_gpr[HEX_REG_FP], pred, cond);
82007540a28STaylor Simpson     gen_log_reg_write_pair(ctx, HEX_REG_FP, RddV);
821dae386b8STaylor Simpson }
822dae386b8STaylor Simpson 
823564b2040STaylor Simpson static void gen_endloop0(DisasContext *ctx)
824564b2040STaylor Simpson {
8257a819de8SRichard Henderson     TCGv lpcfg = tcg_temp_new();
826564b2040STaylor Simpson 
827564b2040STaylor Simpson     GET_USR_FIELD(USR_LPCFG, lpcfg);
828564b2040STaylor Simpson 
829564b2040STaylor Simpson     /*
830564b2040STaylor Simpson      *    if (lpcfg == 1) {
83125e1d87dSTaylor Simpson      *        p3 = 0xff;
832564b2040STaylor Simpson      *    }
833564b2040STaylor Simpson      */
834564b2040STaylor Simpson     TCGLabel *label1 = gen_new_label();
835564b2040STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
836564b2040STaylor Simpson     {
83725e1d87dSTaylor Simpson         gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff));
838564b2040STaylor Simpson     }
839564b2040STaylor Simpson     gen_set_label(label1);
840564b2040STaylor Simpson 
841564b2040STaylor Simpson     /*
842564b2040STaylor Simpson      *    if (lpcfg) {
843564b2040STaylor Simpson      *        SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
844564b2040STaylor Simpson      *    }
845564b2040STaylor Simpson      */
846564b2040STaylor Simpson     TCGLabel *label2 = gen_new_label();
847564b2040STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
848564b2040STaylor Simpson     {
849564b2040STaylor Simpson         tcg_gen_subi_tl(lpcfg, lpcfg, 1);
850148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, USR_LPCFG, lpcfg);
851564b2040STaylor Simpson     }
852564b2040STaylor Simpson     gen_set_label(label2);
853564b2040STaylor Simpson 
854564b2040STaylor Simpson     /*
855564b2040STaylor Simpson      * If we're in a tight loop, we'll do this at the end of the TB to take
856564b2040STaylor Simpson      * advantage of direct block chaining.
857564b2040STaylor Simpson      */
858564b2040STaylor Simpson     if (!ctx->is_tight_loop) {
859564b2040STaylor Simpson         /*
860564b2040STaylor Simpson          *    if (hex_gpr[HEX_REG_LC0] > 1) {
861564b2040STaylor Simpson          *        PC = hex_gpr[HEX_REG_SA0];
862564b2040STaylor Simpson          *        hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
863564b2040STaylor Simpson          *    }
864564b2040STaylor Simpson          */
865564b2040STaylor Simpson         TCGLabel *label3 = gen_new_label();
866564b2040STaylor Simpson         tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
867564b2040STaylor Simpson         {
868e28b77a6STaylor Simpson             TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0);
869564b2040STaylor Simpson             gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
870e28b77a6STaylor Simpson             tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1);
871564b2040STaylor Simpson         }
872564b2040STaylor Simpson         gen_set_label(label3);
873564b2040STaylor Simpson     }
874564b2040STaylor Simpson }
875564b2040STaylor Simpson 
876b8552a78STaylor Simpson static void gen_endloop1(DisasContext *ctx)
877b8552a78STaylor Simpson {
878b8552a78STaylor Simpson     /*
879b8552a78STaylor Simpson      *    if (hex_gpr[HEX_REG_LC1] > 1) {
880b8552a78STaylor Simpson      *        PC = hex_gpr[HEX_REG_SA1];
881b8552a78STaylor Simpson      *        hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
882b8552a78STaylor Simpson      *    }
883b8552a78STaylor Simpson      */
884b8552a78STaylor Simpson     TCGLabel *label = gen_new_label();
885b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, label);
886b8552a78STaylor Simpson     {
887e28b77a6STaylor Simpson         TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1);
888b8552a78STaylor Simpson         gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
889e28b77a6STaylor Simpson         tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1);
890b8552a78STaylor Simpson     }
891b8552a78STaylor Simpson     gen_set_label(label);
892b8552a78STaylor Simpson }
893b8552a78STaylor Simpson 
894b8552a78STaylor Simpson static void gen_endloop01(DisasContext *ctx)
895b8552a78STaylor Simpson {
896b8552a78STaylor Simpson     TCGv lpcfg = tcg_temp_new();
897b8552a78STaylor Simpson     TCGLabel *label1 = gen_new_label();
898b8552a78STaylor Simpson     TCGLabel *label2 = gen_new_label();
899b8552a78STaylor Simpson     TCGLabel *label3 = gen_new_label();
900b8552a78STaylor Simpson     TCGLabel *done = gen_new_label();
901b8552a78STaylor Simpson 
902b8552a78STaylor Simpson     GET_USR_FIELD(USR_LPCFG, lpcfg);
903b8552a78STaylor Simpson 
904b8552a78STaylor Simpson     /*
905b8552a78STaylor Simpson      *    if (lpcfg == 1) {
90625e1d87dSTaylor Simpson      *        p3 = 0xff;
907b8552a78STaylor Simpson      *    }
908b8552a78STaylor Simpson      */
909b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
910b8552a78STaylor Simpson     {
91125e1d87dSTaylor Simpson         gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff));
912b8552a78STaylor Simpson     }
913b8552a78STaylor Simpson     gen_set_label(label1);
914b8552a78STaylor Simpson 
915b8552a78STaylor Simpson     /*
916b8552a78STaylor Simpson      *    if (lpcfg) {
917b8552a78STaylor Simpson      *        SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
918b8552a78STaylor Simpson      *    }
919b8552a78STaylor Simpson      */
920b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
921b8552a78STaylor Simpson     {
922b8552a78STaylor Simpson         tcg_gen_subi_tl(lpcfg, lpcfg, 1);
923148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, USR_LPCFG, lpcfg);
924b8552a78STaylor Simpson     }
925b8552a78STaylor Simpson     gen_set_label(label2);
926b8552a78STaylor Simpson 
927b8552a78STaylor Simpson     /*
928b8552a78STaylor Simpson      *    if (hex_gpr[HEX_REG_LC0] > 1) {
929b8552a78STaylor Simpson      *        PC = hex_gpr[HEX_REG_SA0];
930b8552a78STaylor Simpson      *        hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
931b8552a78STaylor Simpson      *    } else {
932b8552a78STaylor Simpson      *        if (hex_gpr[HEX_REG_LC1] > 1) {
933b8552a78STaylor Simpson      *            hex_next_pc = hex_gpr[HEX_REG_SA1];
934b8552a78STaylor Simpson      *            hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
935b8552a78STaylor Simpson      *        }
936b8552a78STaylor Simpson      *    }
937b8552a78STaylor Simpson      */
938b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
939b8552a78STaylor Simpson     {
940e28b77a6STaylor Simpson         TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0);
941b8552a78STaylor Simpson         gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
942e28b77a6STaylor Simpson         tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1);
943b8552a78STaylor Simpson         tcg_gen_br(done);
944b8552a78STaylor Simpson     }
945b8552a78STaylor Simpson     gen_set_label(label3);
946b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, done);
947b8552a78STaylor Simpson     {
948e28b77a6STaylor Simpson         TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1);
949b8552a78STaylor Simpson         gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
950e28b77a6STaylor Simpson         tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1);
951b8552a78STaylor Simpson     }
952b8552a78STaylor Simpson     gen_set_label(done);
953b8552a78STaylor Simpson }
954b8552a78STaylor Simpson 
95597b16fafSTaylor Simpson static void gen_cmp_jumpnv(DisasContext *ctx,
95697b16fafSTaylor Simpson                            TCGCond cond, TCGv val, TCGv src, int pc_off)
95797b16fafSTaylor Simpson {
95897b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
95997b16fafSTaylor Simpson     tcg_gen_setcond_tl(cond, pred, val, src);
96097b16fafSTaylor Simpson     gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
96197b16fafSTaylor Simpson }
96297b16fafSTaylor Simpson 
96397b16fafSTaylor Simpson static void gen_cmpi_jumpnv(DisasContext *ctx,
96497b16fafSTaylor Simpson                             TCGCond cond, TCGv val, int src, int pc_off)
96597b16fafSTaylor Simpson {
96697b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
96797b16fafSTaylor Simpson     tcg_gen_setcondi_tl(cond, pred, val, src);
96897b16fafSTaylor Simpson     gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
96997b16fafSTaylor Simpson }
97097b16fafSTaylor Simpson 
9718e8a85c1STaylor Simpson /* Shift left with saturation */
972148ef7fdSTaylor Simpson static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt)
9738e8a85c1STaylor Simpson {
974*71ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dst == src */
975148ef7fdSTaylor Simpson     TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
9768e8a85c1STaylor Simpson     TCGv sh32 = tcg_temp_new();
9778e8a85c1STaylor Simpson     TCGv dst_sar = tcg_temp_new();
9788e8a85c1STaylor Simpson     TCGv ovf = tcg_temp_new();
9798e8a85c1STaylor Simpson     TCGv satval = tcg_temp_new();
9808e8a85c1STaylor Simpson     TCGv min = tcg_constant_tl(0x80000000);
9818e8a85c1STaylor Simpson     TCGv max = tcg_constant_tl(0x7fffffff);
9828e8a85c1STaylor Simpson 
9838e8a85c1STaylor Simpson     /*
9848e8a85c1STaylor Simpson      *    Possible values for shift_amt are 0 .. 64
9858e8a85c1STaylor Simpson      *    We need special handling for values above 31
9868e8a85c1STaylor Simpson      *
9878e8a85c1STaylor Simpson      *    sh32 = shift & 31;
9888e8a85c1STaylor Simpson      *    dst = sh32 == shift ? src : 0;
9898e8a85c1STaylor Simpson      *    dst <<= sh32;
9908e8a85c1STaylor Simpson      *    dst_sar = dst >> sh32;
9918e8a85c1STaylor Simpson      *    satval = src < 0 ? min : max;
9928e8a85c1STaylor Simpson      *    if (dst_asr != src) {
9938e8a85c1STaylor Simpson      *        usr.OVF |= 1;
9948e8a85c1STaylor Simpson      *        dst = satval;
9958e8a85c1STaylor Simpson      *    }
9968e8a85c1STaylor Simpson      */
9978e8a85c1STaylor Simpson 
9988e8a85c1STaylor Simpson     tcg_gen_andi_tl(sh32, shift_amt, 31);
999*71ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, tmp, sh32, shift_amt,
10008e8a85c1STaylor Simpson                        src, tcg_constant_tl(0));
1001*71ed3697STaylor Simpson     tcg_gen_shl_tl(tmp, tmp, sh32);
1002*71ed3697STaylor Simpson     tcg_gen_sar_tl(dst_sar, tmp, sh32);
10038e8a85c1STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
10048e8a85c1STaylor Simpson 
10058e8a85c1STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
10068e8a85c1STaylor Simpson     tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
1007148ef7fdSTaylor Simpson     tcg_gen_or_tl(usr, usr, ovf);
10088e8a85c1STaylor Simpson 
1009*71ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, tmp, satval);
10108e8a85c1STaylor Simpson }
10118e8a85c1STaylor Simpson 
10128e8a85c1STaylor Simpson static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
10138e8a85c1STaylor Simpson {
10148e8a85c1STaylor Simpson     /*
10158e8a85c1STaylor Simpson      *  Shift arithmetic right
10168e8a85c1STaylor Simpson      *  Robust when shift_amt is >31 bits
10178e8a85c1STaylor Simpson      */
10188e8a85c1STaylor Simpson     TCGv tmp = tcg_temp_new();
10198e8a85c1STaylor Simpson     tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31));
10208e8a85c1STaylor Simpson     tcg_gen_sar_tl(dst, src, tmp);
10218e8a85c1STaylor Simpson }
10228e8a85c1STaylor Simpson 
10238e8a85c1STaylor Simpson /* Bidirectional shift right with saturation */
1024148ef7fdSTaylor Simpson static void gen_asr_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV)
10258e8a85c1STaylor Simpson {
10267a819de8SRichard Henderson     TCGv shift_amt = tcg_temp_new();
10278e8a85c1STaylor Simpson     TCGLabel *positive = gen_new_label();
10288e8a85c1STaylor Simpson     TCGLabel *done = gen_new_label();
10298e8a85c1STaylor Simpson 
10308e8a85c1STaylor Simpson     tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
10318e8a85c1STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
10328e8a85c1STaylor Simpson 
10338e8a85c1STaylor Simpson     /* Negative shift amount => shift left */
10348e8a85c1STaylor Simpson     tcg_gen_neg_tl(shift_amt, shift_amt);
1035148ef7fdSTaylor Simpson     gen_shl_sat(ctx, RdV, RsV, shift_amt);
10368e8a85c1STaylor Simpson     tcg_gen_br(done);
10378e8a85c1STaylor Simpson 
10388e8a85c1STaylor Simpson     gen_set_label(positive);
10398e8a85c1STaylor Simpson     /* Positive shift amount => shift right */
10408e8a85c1STaylor Simpson     gen_sar(RdV, RsV, shift_amt);
10418e8a85c1STaylor Simpson 
10428e8a85c1STaylor Simpson     gen_set_label(done);
10438e8a85c1STaylor Simpson }
10448e8a85c1STaylor Simpson 
10458e8a85c1STaylor Simpson /* Bidirectional shift left with saturation */
1046148ef7fdSTaylor Simpson static void gen_asl_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV)
10478e8a85c1STaylor Simpson {
10487a819de8SRichard Henderson     TCGv shift_amt = tcg_temp_new();
10498e8a85c1STaylor Simpson     TCGLabel *positive = gen_new_label();
10508e8a85c1STaylor Simpson     TCGLabel *done = gen_new_label();
10518e8a85c1STaylor Simpson 
10528e8a85c1STaylor Simpson     tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
10538e8a85c1STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
10548e8a85c1STaylor Simpson 
10558e8a85c1STaylor Simpson     /* Negative shift amount => shift right */
10568e8a85c1STaylor Simpson     tcg_gen_neg_tl(shift_amt, shift_amt);
10578e8a85c1STaylor Simpson     gen_sar(RdV, RsV, shift_amt);
10588e8a85c1STaylor Simpson     tcg_gen_br(done);
10598e8a85c1STaylor Simpson 
10608e8a85c1STaylor Simpson     gen_set_label(positive);
10618e8a85c1STaylor Simpson     /* Positive shift amount => shift left */
1062148ef7fdSTaylor Simpson     gen_shl_sat(ctx, RdV, RsV, shift_amt);
10638e8a85c1STaylor Simpson 
10648e8a85c1STaylor Simpson     gen_set_label(done);
10658e8a85c1STaylor Simpson }
10668e8a85c1STaylor Simpson 
1067887d61b2STaylor Simpson static intptr_t vreg_src_off(DisasContext *ctx, int num)
1068887d61b2STaylor Simpson {
1069887d61b2STaylor Simpson     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
1070887d61b2STaylor Simpson 
1071887d61b2STaylor Simpson     if (test_bit(num, ctx->vregs_select)) {
1072887d61b2STaylor Simpson         offset = ctx_future_vreg_off(ctx, num, 1, false);
1073887d61b2STaylor Simpson     }
1074887d61b2STaylor Simpson     if (test_bit(num, ctx->vregs_updated_tmp)) {
1075887d61b2STaylor Simpson         offset = ctx_tmp_vreg_off(ctx, num, 1, false);
1076887d61b2STaylor Simpson     }
1077887d61b2STaylor Simpson     return offset;
1078887d61b2STaylor Simpson }
1079887d61b2STaylor Simpson 
1080887d61b2STaylor Simpson static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
1081c2b33d0bSTaylor Simpson                                VRegWriteType type)
1082887d61b2STaylor Simpson {
1083887d61b2STaylor Simpson     intptr_t dstoff;
1084887d61b2STaylor Simpson 
1085887d61b2STaylor Simpson     if (type != EXT_TMP) {
1086887d61b2STaylor Simpson         dstoff = ctx_future_vreg_off(ctx, num, 1, true);
1087887d61b2STaylor Simpson         tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
1088887d61b2STaylor Simpson                          sizeof(MMVector), sizeof(MMVector));
1089887d61b2STaylor Simpson     } else {
1090887d61b2STaylor Simpson         dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
1091887d61b2STaylor Simpson         tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
1092887d61b2STaylor Simpson                          sizeof(MMVector), sizeof(MMVector));
1093887d61b2STaylor Simpson     }
1094887d61b2STaylor Simpson }
1095887d61b2STaylor Simpson 
1096887d61b2STaylor Simpson static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
1097c2b33d0bSTaylor Simpson                                     VRegWriteType type)
1098887d61b2STaylor Simpson {
1099c2b33d0bSTaylor Simpson     gen_log_vreg_write(ctx, srcoff, num ^ 0, type);
1100887d61b2STaylor Simpson     srcoff += sizeof(MMVector);
1101c2b33d0bSTaylor Simpson     gen_log_vreg_write(ctx, srcoff, num ^ 1, type);
1102887d61b2STaylor Simpson }
1103887d61b2STaylor Simpson 
1104c2b33d0bSTaylor Simpson static intptr_t get_result_qreg(DisasContext *ctx, int qnum)
1105887d61b2STaylor Simpson {
1106c2b33d0bSTaylor Simpson     return  offsetof(CPUHexagonState, future_QRegs[qnum]);
1107887d61b2STaylor Simpson }
1108887d61b2STaylor Simpson 
1109887d61b2STaylor Simpson static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
1110887d61b2STaylor Simpson                           bool aligned)
1111887d61b2STaylor Simpson {
1112887d61b2STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
1113887d61b2STaylor Simpson     if (aligned) {
1114887d61b2STaylor Simpson         tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1));
1115887d61b2STaylor Simpson     }
1116887d61b2STaylor Simpson     for (int i = 0; i < sizeof(MMVector) / 8; i++) {
111753b26d25SRichard Henderson         tcg_gen_qemu_ld_i64(tmp, src, ctx->mem_idx, MO_TEUQ);
1118887d61b2STaylor Simpson         tcg_gen_addi_tl(src, src, 8);
1119887d61b2STaylor Simpson         tcg_gen_st_i64(tmp, cpu_env, dstoff + i * 8);
1120887d61b2STaylor Simpson     }
1121887d61b2STaylor Simpson }
1122887d61b2STaylor Simpson 
11231e536334STaylor Simpson static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
11241e536334STaylor Simpson                            int slot, bool aligned)
1125887d61b2STaylor Simpson {
1126887d61b2STaylor Simpson     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
1127887d61b2STaylor Simpson     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
1128887d61b2STaylor Simpson 
11291e536334STaylor Simpson     if (is_gather_store_insn(ctx)) {
1130887d61b2STaylor Simpson         TCGv sl = tcg_constant_tl(slot);
1131887d61b2STaylor Simpson         gen_helper_gather_store(cpu_env, EA, sl);
1132887d61b2STaylor Simpson         return;
1133887d61b2STaylor Simpson     }
1134887d61b2STaylor Simpson 
1135887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
1136887d61b2STaylor Simpson     if (aligned) {
1137887d61b2STaylor Simpson         tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
1138887d61b2STaylor Simpson                         ~((int32_t)sizeof(MMVector) - 1));
1139887d61b2STaylor Simpson     } else {
1140887d61b2STaylor Simpson         tcg_gen_mov_tl(hex_vstore_addr[slot], EA);
1141887d61b2STaylor Simpson     }
1142887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
1143887d61b2STaylor Simpson 
1144887d61b2STaylor Simpson     /* Copy the data to the vstore buffer */
1145887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
1146887d61b2STaylor Simpson     /* Set the mask to all 1's */
1147887d61b2STaylor Simpson     tcg_gen_gvec_dup_imm(MO_64, maskoff, sizeof(MMQReg), sizeof(MMQReg), ~0LL);
1148887d61b2STaylor Simpson }
1149887d61b2STaylor Simpson 
1150887d61b2STaylor Simpson static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
1151887d61b2STaylor Simpson                                   intptr_t bitsoff, int slot, bool invert)
1152887d61b2STaylor Simpson {
1153887d61b2STaylor Simpson     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
1154887d61b2STaylor Simpson     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
1155887d61b2STaylor Simpson 
1156887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
1157887d61b2STaylor Simpson     tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
1158887d61b2STaylor Simpson                     ~((int32_t)sizeof(MMVector) - 1));
1159887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
1160887d61b2STaylor Simpson 
1161887d61b2STaylor Simpson     /* Copy the data to the vstore buffer */
1162887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
1163887d61b2STaylor Simpson     /* Copy the mask */
1164887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, maskoff, bitsoff, sizeof(MMQReg), sizeof(MMQReg));
1165887d61b2STaylor Simpson     if (invert) {
1166887d61b2STaylor Simpson         tcg_gen_gvec_not(MO_64, maskoff, maskoff,
1167887d61b2STaylor Simpson                          sizeof(MMQReg), sizeof(MMQReg));
1168887d61b2STaylor Simpson     }
1169887d61b2STaylor Simpson }
1170887d61b2STaylor Simpson 
1171887d61b2STaylor Simpson static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
1172887d61b2STaylor Simpson {
1173887d61b2STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
1174887d61b2STaylor Simpson     TCGv_i64 word = tcg_temp_new_i64();
1175887d61b2STaylor Simpson     TCGv_i64 bits = tcg_temp_new_i64();
1176887d61b2STaylor Simpson     TCGv_i64 mask = tcg_temp_new_i64();
1177887d61b2STaylor Simpson     TCGv_i64 zero = tcg_constant_i64(0);
1178887d61b2STaylor Simpson     TCGv_i64 ones = tcg_constant_i64(~0);
1179887d61b2STaylor Simpson 
1180887d61b2STaylor Simpson     for (int i = 0; i < sizeof(MMVector) / 8; i++) {
1181887d61b2STaylor Simpson         tcg_gen_ld_i64(tmp, cpu_env, srcoff + i * 8);
1182887d61b2STaylor Simpson         tcg_gen_movi_i64(mask, 0);
1183887d61b2STaylor Simpson 
1184887d61b2STaylor Simpson         for (int j = 0; j < 8; j += size) {
1185887d61b2STaylor Simpson             tcg_gen_extract_i64(word, tmp, j * 8, size * 8);
1186887d61b2STaylor Simpson             tcg_gen_movcond_i64(TCG_COND_NE, bits, word, zero, ones, zero);
1187887d61b2STaylor Simpson             tcg_gen_deposit_i64(mask, mask, bits, j, size);
1188887d61b2STaylor Simpson         }
1189887d61b2STaylor Simpson 
1190887d61b2STaylor Simpson         tcg_gen_st8_i64(mask, cpu_env, dstoff + i);
1191887d61b2STaylor Simpson     }
1192887d61b2STaylor Simpson }
1193887d61b2STaylor Simpson 
11947e8b3b39SPaolo Montesel void probe_noshuf_load(TCGv va, int s, int mi)
119515fc6badSTaylor Simpson {
119615fc6badSTaylor Simpson     TCGv size = tcg_constant_tl(s);
119715fc6badSTaylor Simpson     TCGv mem_idx = tcg_constant_tl(mi);
119815fc6badSTaylor Simpson     gen_helper_probe_noshuf_load(cpu_env, va, size, mem_idx);
119915fc6badSTaylor Simpson }
120015fc6badSTaylor Simpson 
120142659e04SNiccolò Izzo /*
120242659e04SNiccolò Izzo  * Note: Since this function might branch, `val` is
120342659e04SNiccolò Izzo  * required to be a `tcg_temp_local`.
120442659e04SNiccolò Izzo  */
1205148ef7fdSTaylor Simpson void gen_set_usr_field_if(DisasContext *ctx, int field, TCGv val)
120642659e04SNiccolò Izzo {
120742659e04SNiccolò Izzo     /* Sets the USR field if `val` is non-zero */
120842659e04SNiccolò Izzo     if (reg_field_info[field].width == 1) {
1209148ef7fdSTaylor Simpson         TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
121042659e04SNiccolò Izzo         TCGv tmp = tcg_temp_new();
121142659e04SNiccolò Izzo         tcg_gen_extract_tl(tmp, val, 0, reg_field_info[field].width);
121242659e04SNiccolò Izzo         tcg_gen_shli_tl(tmp, tmp, reg_field_info[field].offset);
1213148ef7fdSTaylor Simpson         tcg_gen_or_tl(usr, usr, tmp);
121442659e04SNiccolò Izzo     } else {
121542659e04SNiccolò Izzo         TCGLabel *skip_label = gen_new_label();
121642659e04SNiccolò Izzo         tcg_gen_brcondi_tl(TCG_COND_EQ, val, 0, skip_label);
1217148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, field, val);
121842659e04SNiccolò Izzo         gen_set_label(skip_label);
121942659e04SNiccolò Izzo     }
122042659e04SNiccolò Izzo }
122142659e04SNiccolò Izzo 
122242659e04SNiccolò Izzo void gen_sat_i32(TCGv dest, TCGv source, int width)
122342659e04SNiccolò Izzo {
122442659e04SNiccolò Izzo     TCGv max_val = tcg_constant_tl((1 << (width - 1)) - 1);
122542659e04SNiccolò Izzo     TCGv min_val = tcg_constant_tl(-(1 << (width - 1)));
122642659e04SNiccolò Izzo     tcg_gen_smin_tl(dest, source, max_val);
122742659e04SNiccolò Izzo     tcg_gen_smax_tl(dest, dest, min_val);
122842659e04SNiccolò Izzo }
122942659e04SNiccolò Izzo 
123042659e04SNiccolò Izzo void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
123142659e04SNiccolò Izzo {
1232*71ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dest == source */
1233*71ed3697STaylor Simpson     gen_sat_i32(tmp, source, width);
1234*71ed3697STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
1235*71ed3697STaylor Simpson     tcg_gen_mov_tl(dest, tmp);
123642659e04SNiccolò Izzo }
123742659e04SNiccolò Izzo 
123842659e04SNiccolò Izzo void gen_satu_i32(TCGv dest, TCGv source, int width)
123942659e04SNiccolò Izzo {
1240*71ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dest == source */
124142659e04SNiccolò Izzo     TCGv max_val = tcg_constant_tl((1 << width) - 1);
124242659e04SNiccolò Izzo     TCGv zero = tcg_constant_tl(0);
1243*71ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_GTU, tmp, source, max_val, max_val, source);
1244*71ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_LT, tmp, source, zero, zero, tmp);
1245*71ed3697STaylor Simpson     tcg_gen_mov_tl(dest, tmp);
124642659e04SNiccolò Izzo }
124742659e04SNiccolò Izzo 
124842659e04SNiccolò Izzo void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
124942659e04SNiccolò Izzo {
1250*71ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dest == source */
1251*71ed3697STaylor Simpson     gen_satu_i32(tmp, source, width);
1252*71ed3697STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
1253*71ed3697STaylor Simpson     tcg_gen_mov_tl(dest, tmp);
125442659e04SNiccolò Izzo }
125542659e04SNiccolò Izzo 
125642659e04SNiccolò Izzo void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
125742659e04SNiccolò Izzo {
125842659e04SNiccolò Izzo     TCGv_i64 max_val = tcg_constant_i64((1LL << (width - 1)) - 1LL);
125942659e04SNiccolò Izzo     TCGv_i64 min_val = tcg_constant_i64(-(1LL << (width - 1)));
126042659e04SNiccolò Izzo     tcg_gen_smin_i64(dest, source, max_val);
126142659e04SNiccolò Izzo     tcg_gen_smax_i64(dest, dest, min_val);
126242659e04SNiccolò Izzo }
126342659e04SNiccolò Izzo 
126442659e04SNiccolò Izzo void gen_sat_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
126542659e04SNiccolò Izzo {
1266*71ed3697STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
126742659e04SNiccolò Izzo     TCGv_i64 ovfl_64;
1268*71ed3697STaylor Simpson     gen_sat_i64(tmp, source, width);
126942659e04SNiccolò Izzo     ovfl_64 = tcg_temp_new_i64();
1270*71ed3697STaylor Simpson     tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
1271*71ed3697STaylor Simpson     tcg_gen_mov_i64(dest, tmp);
127242659e04SNiccolò Izzo     tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
127342659e04SNiccolò Izzo }
127442659e04SNiccolò Izzo 
127542659e04SNiccolò Izzo void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width)
127642659e04SNiccolò Izzo {
1277*71ed3697STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();    /* In case dest == source */
127842659e04SNiccolò Izzo     TCGv_i64 max_val = tcg_constant_i64((1LL << width) - 1LL);
127942659e04SNiccolò Izzo     TCGv_i64 zero = tcg_constant_i64(0);
1280*71ed3697STaylor Simpson     tcg_gen_movcond_i64(TCG_COND_GTU, tmp, source, max_val, max_val, source);
1281*71ed3697STaylor Simpson     tcg_gen_movcond_i64(TCG_COND_LT, tmp, source, zero, zero, tmp);
1282*71ed3697STaylor Simpson     tcg_gen_mov_i64(dest, tmp);
128342659e04SNiccolò Izzo }
128442659e04SNiccolò Izzo 
128542659e04SNiccolò Izzo void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
128642659e04SNiccolò Izzo {
1287*71ed3697STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();    /* In case dest == source */
128842659e04SNiccolò Izzo     TCGv_i64 ovfl_64;
1289*71ed3697STaylor Simpson     gen_satu_i64(tmp, source, width);
129042659e04SNiccolò Izzo     ovfl_64 = tcg_temp_new_i64();
1291*71ed3697STaylor Simpson     tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
1292*71ed3697STaylor Simpson     tcg_gen_mov_i64(dest, tmp);
129342659e04SNiccolò Izzo     tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
129442659e04SNiccolò Izzo }
129542659e04SNiccolò Izzo 
129642659e04SNiccolò Izzo /* Implements the fADDSAT64 macro in TCG */
1297148ef7fdSTaylor Simpson void gen_add_sat_i64(DisasContext *ctx, TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
129842659e04SNiccolò Izzo {
12997a819de8SRichard Henderson     TCGv_i64 sum = tcg_temp_new_i64();
130042659e04SNiccolò Izzo     TCGv_i64 xor = tcg_temp_new_i64();
130142659e04SNiccolò Izzo     TCGv_i64 cond1 = tcg_temp_new_i64();
13027a819de8SRichard Henderson     TCGv_i64 cond2 = tcg_temp_new_i64();
130342659e04SNiccolò Izzo     TCGv_i64 cond3 = tcg_temp_new_i64();
130442659e04SNiccolò Izzo     TCGv_i64 mask = tcg_constant_i64(0x8000000000000000ULL);
130542659e04SNiccolò Izzo     TCGv_i64 max_pos = tcg_constant_i64(0x7FFFFFFFFFFFFFFFLL);
130642659e04SNiccolò Izzo     TCGv_i64 max_neg = tcg_constant_i64(0x8000000000000000LL);
130742659e04SNiccolò Izzo     TCGv_i64 zero = tcg_constant_i64(0);
130842659e04SNiccolò Izzo     TCGLabel *no_ovfl_label = gen_new_label();
130942659e04SNiccolò Izzo     TCGLabel *ovfl_label = gen_new_label();
131042659e04SNiccolò Izzo     TCGLabel *ret_label = gen_new_label();
131142659e04SNiccolò Izzo 
131242659e04SNiccolò Izzo     tcg_gen_add_i64(sum, a, b);
131342659e04SNiccolò Izzo     tcg_gen_xor_i64(xor, a, b);
131442659e04SNiccolò Izzo 
131542659e04SNiccolò Izzo     /* if (xor & mask) */
131642659e04SNiccolò Izzo     tcg_gen_and_i64(cond1, xor, mask);
131742659e04SNiccolò Izzo     tcg_gen_brcondi_i64(TCG_COND_NE, cond1, 0, no_ovfl_label);
131842659e04SNiccolò Izzo 
131942659e04SNiccolò Izzo     /* else if ((a ^ sum) & mask) */
132042659e04SNiccolò Izzo     tcg_gen_xor_i64(cond2, a, sum);
132142659e04SNiccolò Izzo     tcg_gen_and_i64(cond2, cond2, mask);
132242659e04SNiccolò Izzo     tcg_gen_brcondi_i64(TCG_COND_NE, cond2, 0, ovfl_label);
132342659e04SNiccolò Izzo     /* fallthrough to no_ovfl_label branch */
132442659e04SNiccolò Izzo 
132542659e04SNiccolò Izzo     /* if branch */
132642659e04SNiccolò Izzo     gen_set_label(no_ovfl_label);
132742659e04SNiccolò Izzo     tcg_gen_mov_i64(ret, sum);
132842659e04SNiccolò Izzo     tcg_gen_br(ret_label);
132942659e04SNiccolò Izzo 
133042659e04SNiccolò Izzo     /* else if branch */
133142659e04SNiccolò Izzo     gen_set_label(ovfl_label);
133242659e04SNiccolò Izzo     tcg_gen_and_i64(cond3, sum, mask);
133342659e04SNiccolò Izzo     tcg_gen_movcond_i64(TCG_COND_NE, ret, cond3, zero, max_pos, max_neg);
1334148ef7fdSTaylor Simpson     gen_set_usr_fieldi(ctx, USR_OVF, 1);
133542659e04SNiccolò Izzo 
133642659e04SNiccolò Izzo     gen_set_label(ret_label);
133742659e04SNiccolò Izzo }
133842659e04SNiccolò Izzo 
133957acfcdeSTaylor Simpson #include "tcg_funcs_generated.c.inc"
134057acfcdeSTaylor Simpson #include "tcg_func_table_generated.c.inc"
1341