xref: /openbmc/qemu/target/hexagon/genptr.c (revision 1b9a7f2a)
157acfcdeSTaylor Simpson /*
2c0d86060STaylor Simpson  *  Copyright(c) 2019-2022 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"
3257acfcdeSTaylor Simpson 
3357acfcdeSTaylor Simpson static inline void gen_log_predicated_reg_write(int rnum, TCGv val, int slot)
3457acfcdeSTaylor Simpson {
3523803bbeSPhilippe Mathieu-Daudé     TCGv zero = tcg_constant_tl(0);
3657acfcdeSTaylor Simpson     TCGv slot_mask = tcg_temp_new();
3757acfcdeSTaylor Simpson 
3857acfcdeSTaylor Simpson     tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
3957acfcdeSTaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero,
4057acfcdeSTaylor Simpson                            val, hex_new_value[rnum]);
4185580a65STaylor Simpson     if (HEX_DEBUG) {
42d799f8adSTaylor Simpson         /*
43d799f8adSTaylor Simpson          * Do this so HELPER(debug_commit_end) will know
44d799f8adSTaylor Simpson          *
45d799f8adSTaylor Simpson          * Note that slot_mask indicates the value is not written
46d799f8adSTaylor Simpson          * (i.e., slot was cancelled), so we create a true/false value before
47d799f8adSTaylor Simpson          * or'ing with hex_reg_written[rnum].
48d799f8adSTaylor Simpson          */
49d799f8adSTaylor Simpson         tcg_gen_setcond_tl(TCG_COND_EQ, slot_mask, slot_mask, zero);
50d799f8adSTaylor Simpson         tcg_gen_or_tl(hex_reg_written[rnum], hex_reg_written[rnum], slot_mask);
5185580a65STaylor Simpson     }
5257acfcdeSTaylor Simpson 
5357acfcdeSTaylor Simpson     tcg_temp_free(slot_mask);
5457acfcdeSTaylor Simpson }
5557acfcdeSTaylor Simpson 
5657acfcdeSTaylor Simpson static inline void gen_log_reg_write(int rnum, TCGv val)
5757acfcdeSTaylor Simpson {
5857acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_new_value[rnum], val);
5985580a65STaylor Simpson     if (HEX_DEBUG) {
6057acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
6157acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum], 1);
6285580a65STaylor Simpson     }
6357acfcdeSTaylor Simpson }
6457acfcdeSTaylor Simpson 
6557acfcdeSTaylor Simpson static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val, int slot)
6657acfcdeSTaylor Simpson {
6757acfcdeSTaylor Simpson     TCGv val32 = tcg_temp_new();
6823803bbeSPhilippe Mathieu-Daudé     TCGv zero = tcg_constant_tl(0);
6957acfcdeSTaylor Simpson     TCGv slot_mask = tcg_temp_new();
7057acfcdeSTaylor Simpson 
7157acfcdeSTaylor Simpson     tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
7257acfcdeSTaylor Simpson     /* Low word */
7357acfcdeSTaylor Simpson     tcg_gen_extrl_i64_i32(val32, val);
74edf26adeSTaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum],
7557acfcdeSTaylor Simpson                        slot_mask, zero,
76edf26adeSTaylor Simpson                        val32, hex_new_value[rnum]);
7757acfcdeSTaylor Simpson     /* High word */
7857acfcdeSTaylor Simpson     tcg_gen_extrh_i64_i32(val32, val);
7957acfcdeSTaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum + 1],
8057acfcdeSTaylor Simpson                        slot_mask, zero,
8157acfcdeSTaylor Simpson                        val32, hex_new_value[rnum + 1]);
8285580a65STaylor Simpson     if (HEX_DEBUG) {
83edf26adeSTaylor Simpson         /*
84edf26adeSTaylor Simpson          * Do this so HELPER(debug_commit_end) will know
85edf26adeSTaylor Simpson          *
86edf26adeSTaylor Simpson          * Note that slot_mask indicates the value is not written
87edf26adeSTaylor Simpson          * (i.e., slot was cancelled), so we create a true/false value before
88edf26adeSTaylor Simpson          * or'ing with hex_reg_written[rnum].
89edf26adeSTaylor Simpson          */
90edf26adeSTaylor Simpson         tcg_gen_setcond_tl(TCG_COND_EQ, slot_mask, slot_mask, zero);
91edf26adeSTaylor Simpson         tcg_gen_or_tl(hex_reg_written[rnum], hex_reg_written[rnum], slot_mask);
92edf26adeSTaylor Simpson         tcg_gen_or_tl(hex_reg_written[rnum + 1], hex_reg_written[rnum + 1],
93edf26adeSTaylor Simpson                       slot_mask);
9485580a65STaylor Simpson     }
9557acfcdeSTaylor Simpson 
9657acfcdeSTaylor Simpson     tcg_temp_free(val32);
9757acfcdeSTaylor Simpson     tcg_temp_free(slot_mask);
9857acfcdeSTaylor Simpson }
9957acfcdeSTaylor Simpson 
10057acfcdeSTaylor Simpson static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
10157acfcdeSTaylor Simpson {
10257acfcdeSTaylor Simpson     /* Low word */
10357acfcdeSTaylor Simpson     tcg_gen_extrl_i64_i32(hex_new_value[rnum], val);
10485580a65STaylor Simpson     if (HEX_DEBUG) {
10557acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
10657acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum], 1);
10785580a65STaylor Simpson     }
10857acfcdeSTaylor Simpson 
10957acfcdeSTaylor Simpson     /* High word */
11057acfcdeSTaylor Simpson     tcg_gen_extrh_i64_i32(hex_new_value[rnum + 1], val);
11185580a65STaylor Simpson     if (HEX_DEBUG) {
11257acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
11357acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1);
11485580a65STaylor Simpson     }
11557acfcdeSTaylor Simpson }
11657acfcdeSTaylor Simpson 
1176c677c60STaylor Simpson static inline void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
11857acfcdeSTaylor Simpson {
11957acfcdeSTaylor Simpson     TCGv base_val = tcg_temp_new();
12057acfcdeSTaylor Simpson 
12157acfcdeSTaylor Simpson     tcg_gen_andi_tl(base_val, val, 0xff);
1226c677c60STaylor Simpson 
1236c677c60STaylor Simpson     /*
1246c677c60STaylor Simpson      * Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual
1256c677c60STaylor Simpson      *
1266c677c60STaylor Simpson      * Multiple writes to the same preg are and'ed together
1276c677c60STaylor Simpson      * If this is the first predicate write in the packet, do a
1286c677c60STaylor Simpson      * straight assignment.  Otherwise, do an and.
1296c677c60STaylor Simpson      */
1306c677c60STaylor Simpson     if (!test_bit(pnum, ctx->pregs_written)) {
1316c677c60STaylor Simpson         tcg_gen_mov_tl(hex_new_pred_value[pnum], base_val);
1326c677c60STaylor Simpson     } else {
1336c677c60STaylor Simpson         tcg_gen_and_tl(hex_new_pred_value[pnum],
1346c677c60STaylor Simpson                        hex_new_pred_value[pnum], base_val);
1356c677c60STaylor Simpson     }
13657acfcdeSTaylor Simpson     tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
13757acfcdeSTaylor Simpson 
13857acfcdeSTaylor Simpson     tcg_temp_free(base_val);
13957acfcdeSTaylor Simpson }
14057acfcdeSTaylor Simpson 
14157acfcdeSTaylor Simpson static inline void gen_read_p3_0(TCGv control_reg)
14257acfcdeSTaylor Simpson {
14357acfcdeSTaylor Simpson     tcg_gen_movi_tl(control_reg, 0);
14457acfcdeSTaylor Simpson     for (int i = 0; i < NUM_PREGS; i++) {
14557acfcdeSTaylor Simpson         tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8);
14657acfcdeSTaylor Simpson     }
14757acfcdeSTaylor Simpson }
14857acfcdeSTaylor Simpson 
14957acfcdeSTaylor Simpson /*
15057acfcdeSTaylor Simpson  * Certain control registers require special handling on read
15157acfcdeSTaylor Simpson  *     HEX_REG_P3_0          aliased to the predicate registers
15257acfcdeSTaylor Simpson  *                           -> concat the 4 predicate registers together
15357acfcdeSTaylor Simpson  *     HEX_REG_PC            actual value stored in DisasContext
15457acfcdeSTaylor Simpson  *                           -> assign from ctx->base.pc_next
15557acfcdeSTaylor Simpson  *     HEX_REG_QEMU_*_CNT    changes in current TB in DisasContext
15657acfcdeSTaylor Simpson  *                           -> add current TB changes to existing reg value
15757acfcdeSTaylor Simpson  */
15857acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
15957acfcdeSTaylor Simpson                                      TCGv dest)
16057acfcdeSTaylor Simpson {
16157acfcdeSTaylor Simpson     if (reg_num == HEX_REG_P3_0) {
16257acfcdeSTaylor Simpson         gen_read_p3_0(dest);
16357acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_PC) {
16457acfcdeSTaylor Simpson         tcg_gen_movi_tl(dest, ctx->base.pc_next);
16557acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
16657acfcdeSTaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT],
16757acfcdeSTaylor Simpson                         ctx->num_packets);
16857acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_INSN_CNT) {
16957acfcdeSTaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT],
17057acfcdeSTaylor Simpson                         ctx->num_insns);
171a82dd548STaylor Simpson     } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
172a82dd548STaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_HVX_CNT],
173a82dd548STaylor Simpson                         ctx->num_hvx_insns);
17457acfcdeSTaylor Simpson     } else {
17557acfcdeSTaylor Simpson         tcg_gen_mov_tl(dest, hex_gpr[reg_num]);
17657acfcdeSTaylor Simpson     }
17757acfcdeSTaylor Simpson }
17857acfcdeSTaylor Simpson 
17957acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
18057acfcdeSTaylor Simpson                                           TCGv_i64 dest)
18157acfcdeSTaylor Simpson {
18257acfcdeSTaylor Simpson     if (reg_num == HEX_REG_P3_0) {
18357acfcdeSTaylor Simpson         TCGv p3_0 = tcg_temp_new();
18457acfcdeSTaylor Simpson         gen_read_p3_0(p3_0);
18557acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
18657acfcdeSTaylor Simpson         tcg_temp_free(p3_0);
18757acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_PC - 1) {
18823803bbeSPhilippe Mathieu-Daudé         TCGv pc = tcg_constant_tl(ctx->base.pc_next);
18957acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc);
19057acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
19157acfcdeSTaylor Simpson         TCGv pkt_cnt = tcg_temp_new();
19257acfcdeSTaylor Simpson         TCGv insn_cnt = tcg_temp_new();
19357acfcdeSTaylor Simpson         tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT],
19457acfcdeSTaylor Simpson                         ctx->num_packets);
19557acfcdeSTaylor Simpson         tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT],
19657acfcdeSTaylor Simpson                         ctx->num_insns);
19757acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt);
19857acfcdeSTaylor Simpson         tcg_temp_free(pkt_cnt);
19957acfcdeSTaylor Simpson         tcg_temp_free(insn_cnt);
200a82dd548STaylor Simpson     } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
201a82dd548STaylor Simpson         TCGv hvx_cnt = tcg_temp_new();
202a82dd548STaylor Simpson         tcg_gen_addi_tl(hvx_cnt, hex_gpr[HEX_REG_QEMU_HVX_CNT],
203a82dd548STaylor Simpson                         ctx->num_hvx_insns);
204a82dd548STaylor Simpson         tcg_gen_concat_i32_i64(dest, hvx_cnt, hex_gpr[reg_num + 1]);
205a82dd548STaylor Simpson         tcg_temp_free(hvx_cnt);
20657acfcdeSTaylor Simpson     } else {
20757acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest,
20857acfcdeSTaylor Simpson             hex_gpr[reg_num],
20957acfcdeSTaylor Simpson             hex_gpr[reg_num + 1]);
21057acfcdeSTaylor Simpson     }
21157acfcdeSTaylor Simpson }
21257acfcdeSTaylor Simpson 
213c0d86060STaylor Simpson static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg)
21457acfcdeSTaylor Simpson {
215c0d86060STaylor Simpson     TCGv hex_p8 = tcg_temp_new();
21657acfcdeSTaylor Simpson     for (int i = 0; i < NUM_PREGS; i++) {
217c0d86060STaylor Simpson         tcg_gen_extract_tl(hex_p8, control_reg, i * 8, 8);
218c0d86060STaylor Simpson         gen_log_pred_write(ctx, i, hex_p8);
219c0d86060STaylor Simpson         ctx_log_pred_write(ctx, i);
22057acfcdeSTaylor Simpson     }
221c0d86060STaylor Simpson     tcg_temp_free(hex_p8);
22257acfcdeSTaylor Simpson }
22357acfcdeSTaylor Simpson 
22457acfcdeSTaylor Simpson /*
22557acfcdeSTaylor Simpson  * Certain control registers require special handling on write
22657acfcdeSTaylor Simpson  *     HEX_REG_P3_0          aliased to the predicate registers
22757acfcdeSTaylor Simpson  *                           -> break the value across 4 predicate registers
22857acfcdeSTaylor Simpson  *     HEX_REG_QEMU_*_CNT    changes in current TB in DisasContext
22957acfcdeSTaylor Simpson  *                            -> clear the changes
23057acfcdeSTaylor Simpson  */
23157acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
23257acfcdeSTaylor Simpson                                       TCGv val)
23357acfcdeSTaylor Simpson {
23457acfcdeSTaylor Simpson     if (reg_num == HEX_REG_P3_0) {
235c0d86060STaylor Simpson         gen_write_p3_0(ctx, val);
23657acfcdeSTaylor Simpson     } else {
23757acfcdeSTaylor Simpson         gen_log_reg_write(reg_num, val);
23857acfcdeSTaylor Simpson         ctx_log_reg_write(ctx, reg_num);
23957acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_PKT_CNT) {
24057acfcdeSTaylor Simpson             ctx->num_packets = 0;
24157acfcdeSTaylor Simpson         }
24257acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_INSN_CNT) {
24357acfcdeSTaylor Simpson             ctx->num_insns = 0;
24457acfcdeSTaylor Simpson         }
245a82dd548STaylor Simpson         if (reg_num == HEX_REG_QEMU_HVX_CNT) {
246a82dd548STaylor Simpson             ctx->num_hvx_insns = 0;
247a82dd548STaylor Simpson         }
24857acfcdeSTaylor Simpson     }
24957acfcdeSTaylor Simpson }
25057acfcdeSTaylor Simpson 
25157acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
25257acfcdeSTaylor Simpson                                            TCGv_i64 val)
25357acfcdeSTaylor Simpson {
25457acfcdeSTaylor Simpson     if (reg_num == HEX_REG_P3_0) {
25557acfcdeSTaylor Simpson         TCGv val32 = tcg_temp_new();
25657acfcdeSTaylor Simpson         tcg_gen_extrl_i64_i32(val32, val);
257c0d86060STaylor Simpson         gen_write_p3_0(ctx, val32);
25857acfcdeSTaylor Simpson         tcg_gen_extrh_i64_i32(val32, val);
25957acfcdeSTaylor Simpson         gen_log_reg_write(reg_num + 1, val32);
26057acfcdeSTaylor Simpson         tcg_temp_free(val32);
26157acfcdeSTaylor Simpson         ctx_log_reg_write(ctx, reg_num + 1);
26257acfcdeSTaylor Simpson     } else {
26357acfcdeSTaylor Simpson         gen_log_reg_write_pair(reg_num, val);
26457acfcdeSTaylor Simpson         ctx_log_reg_write_pair(ctx, reg_num);
26557acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_PKT_CNT) {
26657acfcdeSTaylor Simpson             ctx->num_packets = 0;
26757acfcdeSTaylor Simpson             ctx->num_insns = 0;
26857acfcdeSTaylor Simpson         }
269a82dd548STaylor Simpson         if (reg_num == HEX_REG_QEMU_HVX_CNT) {
270a82dd548STaylor Simpson             ctx->num_hvx_insns = 0;
271a82dd548STaylor Simpson         }
27257acfcdeSTaylor Simpson     }
27357acfcdeSTaylor Simpson }
27457acfcdeSTaylor Simpson 
27546ef47e2STaylor Simpson static TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign)
27646ef47e2STaylor Simpson {
27746ef47e2STaylor Simpson     if (sign) {
27846ef47e2STaylor Simpson         tcg_gen_sextract_tl(result, src, N * 8, 8);
27946ef47e2STaylor Simpson     } else {
28046ef47e2STaylor Simpson         tcg_gen_extract_tl(result, src, N * 8, 8);
28146ef47e2STaylor Simpson     }
28246ef47e2STaylor Simpson     return result;
28346ef47e2STaylor Simpson }
28446ef47e2STaylor Simpson 
2850a65d286STaylor Simpson static TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign)
2860a65d286STaylor Simpson {
2870a65d286STaylor Simpson     TCGv_i64 res64 = tcg_temp_new_i64();
2880a65d286STaylor Simpson     if (sign) {
2890a65d286STaylor Simpson         tcg_gen_sextract_i64(res64, src, N * 8, 8);
2900a65d286STaylor Simpson     } else {
2910a65d286STaylor Simpson         tcg_gen_extract_i64(res64, src, N * 8, 8);
2920a65d286STaylor Simpson     }
2930a65d286STaylor Simpson     tcg_gen_extrl_i64_i32(result, res64);
2940a65d286STaylor Simpson     tcg_temp_free_i64(res64);
2950a65d286STaylor Simpson 
2960a65d286STaylor Simpson     return result;
2970a65d286STaylor Simpson }
2980a65d286STaylor Simpson 
29946ef47e2STaylor Simpson static inline TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign)
30046ef47e2STaylor Simpson {
30146ef47e2STaylor Simpson     if (sign) {
30246ef47e2STaylor Simpson         tcg_gen_sextract_tl(result, src, N * 16, 16);
30346ef47e2STaylor Simpson     } else {
30446ef47e2STaylor Simpson         tcg_gen_extract_tl(result, src, N * 16, 16);
30546ef47e2STaylor Simpson     }
30646ef47e2STaylor Simpson     return result;
30746ef47e2STaylor Simpson }
30846ef47e2STaylor Simpson 
3090d0b91a8STaylor Simpson static inline void gen_set_half(int N, TCGv result, TCGv src)
3100d0b91a8STaylor Simpson {
3110d0b91a8STaylor Simpson     tcg_gen_deposit_tl(result, result, src, N * 16, 16);
3120d0b91a8STaylor Simpson }
3130d0b91a8STaylor Simpson 
3140d0b91a8STaylor Simpson static inline void gen_set_half_i64(int N, TCGv_i64 result, TCGv src)
3150d0b91a8STaylor Simpson {
3160d0b91a8STaylor Simpson     TCGv_i64 src64 = tcg_temp_new_i64();
3170d0b91a8STaylor Simpson     tcg_gen_extu_i32_i64(src64, src);
3180d0b91a8STaylor Simpson     tcg_gen_deposit_i64(result, result, src64, N * 16, 16);
3190d0b91a8STaylor Simpson     tcg_temp_free_i64(src64);
3200d0b91a8STaylor Simpson }
3210d0b91a8STaylor Simpson 
3220a65d286STaylor Simpson static void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src)
3230a65d286STaylor Simpson {
3240a65d286STaylor Simpson     TCGv_i64 src64 = tcg_temp_new_i64();
3250a65d286STaylor Simpson     tcg_gen_extu_i32_i64(src64, src);
3260a65d286STaylor Simpson     tcg_gen_deposit_i64(result, result, src64, N * 8, 8);
3270a65d286STaylor Simpson     tcg_temp_free_i64(src64);
3280a65d286STaylor Simpson }
3290a65d286STaylor Simpson 
33057acfcdeSTaylor Simpson static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index)
33157acfcdeSTaylor Simpson {
33257acfcdeSTaylor Simpson     tcg_gen_qemu_ld32u(dest, vaddr, mem_index);
33357acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_addr, vaddr);
33457acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_val, dest);
33557acfcdeSTaylor Simpson }
33657acfcdeSTaylor Simpson 
33757acfcdeSTaylor Simpson static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index)
33857acfcdeSTaylor Simpson {
33957acfcdeSTaylor Simpson     tcg_gen_qemu_ld64(dest, vaddr, mem_index);
34057acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_addr, vaddr);
34157acfcdeSTaylor Simpson     tcg_gen_mov_i64(hex_llsc_val_i64, dest);
34257acfcdeSTaylor Simpson }
34357acfcdeSTaylor Simpson 
34488725336STaylor Simpson static inline void gen_store_conditional4(DisasContext *ctx,
34557acfcdeSTaylor Simpson                                           TCGv pred, TCGv vaddr, TCGv src)
34657acfcdeSTaylor Simpson {
34757acfcdeSTaylor Simpson     TCGLabel *fail = gen_new_label();
34857acfcdeSTaylor Simpson     TCGLabel *done = gen_new_label();
34957acfcdeSTaylor Simpson     TCGv one, zero, tmp;
35057acfcdeSTaylor Simpson 
35157acfcdeSTaylor Simpson     tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
35257acfcdeSTaylor Simpson 
35323803bbeSPhilippe Mathieu-Daudé     one = tcg_constant_tl(0xff);
35423803bbeSPhilippe Mathieu-Daudé     zero = tcg_constant_tl(0);
35557acfcdeSTaylor Simpson     tmp = tcg_temp_new();
35657acfcdeSTaylor Simpson     tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src,
35757acfcdeSTaylor Simpson                               ctx->mem_idx, MO_32);
35888725336STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, pred, tmp, hex_llsc_val,
35957acfcdeSTaylor Simpson                        one, zero);
36057acfcdeSTaylor Simpson     tcg_temp_free(tmp);
36157acfcdeSTaylor Simpson     tcg_gen_br(done);
36257acfcdeSTaylor Simpson 
36357acfcdeSTaylor Simpson     gen_set_label(fail);
36457acfcdeSTaylor Simpson     tcg_gen_movi_tl(pred, 0);
36557acfcdeSTaylor Simpson 
36657acfcdeSTaylor Simpson     gen_set_label(done);
36757acfcdeSTaylor Simpson     tcg_gen_movi_tl(hex_llsc_addr, ~0);
36857acfcdeSTaylor Simpson }
36957acfcdeSTaylor Simpson 
37088725336STaylor Simpson static inline void gen_store_conditional8(DisasContext *ctx,
37157acfcdeSTaylor Simpson                                           TCGv pred, TCGv vaddr, TCGv_i64 src)
37257acfcdeSTaylor Simpson {
37357acfcdeSTaylor Simpson     TCGLabel *fail = gen_new_label();
37457acfcdeSTaylor Simpson     TCGLabel *done = gen_new_label();
37557acfcdeSTaylor Simpson     TCGv_i64 one, zero, tmp;
37657acfcdeSTaylor Simpson 
37757acfcdeSTaylor Simpson     tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
37857acfcdeSTaylor Simpson 
37923803bbeSPhilippe Mathieu-Daudé     one = tcg_constant_i64(0xff);
38023803bbeSPhilippe Mathieu-Daudé     zero = tcg_constant_i64(0);
38157acfcdeSTaylor Simpson     tmp = tcg_temp_new_i64();
38257acfcdeSTaylor Simpson     tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src,
38357acfcdeSTaylor Simpson                                ctx->mem_idx, MO_64);
38457acfcdeSTaylor Simpson     tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64,
38557acfcdeSTaylor Simpson                         one, zero);
38688725336STaylor Simpson     tcg_gen_extrl_i64_i32(pred, tmp);
38757acfcdeSTaylor Simpson     tcg_temp_free_i64(tmp);
38857acfcdeSTaylor Simpson     tcg_gen_br(done);
38957acfcdeSTaylor Simpson 
39057acfcdeSTaylor Simpson     gen_set_label(fail);
39157acfcdeSTaylor Simpson     tcg_gen_movi_tl(pred, 0);
39257acfcdeSTaylor Simpson 
39357acfcdeSTaylor Simpson     gen_set_label(done);
39457acfcdeSTaylor Simpson     tcg_gen_movi_tl(hex_llsc_addr, ~0);
39557acfcdeSTaylor Simpson }
39657acfcdeSTaylor Simpson 
39746ef47e2STaylor Simpson static inline void gen_store32(TCGv vaddr, TCGv src, int width, int slot)
39846ef47e2STaylor Simpson {
39946ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
40046ef47e2STaylor Simpson     tcg_gen_movi_tl(hex_store_width[slot], width);
40146ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_val32[slot], src);
40246ef47e2STaylor Simpson }
40346ef47e2STaylor Simpson 
404661ad999STaylor Simpson static inline void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, int slot)
40546ef47e2STaylor Simpson {
40646ef47e2STaylor Simpson     gen_store32(vaddr, src, 1, slot);
40746ef47e2STaylor Simpson }
40846ef47e2STaylor Simpson 
409661ad999STaylor Simpson static inline void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, int slot)
41046ef47e2STaylor Simpson {
41123803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
412661ad999STaylor Simpson     gen_store1(cpu_env, vaddr, tmp, slot);
41346ef47e2STaylor Simpson }
41446ef47e2STaylor Simpson 
415661ad999STaylor Simpson static inline void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, int slot)
41646ef47e2STaylor Simpson {
41746ef47e2STaylor Simpson     gen_store32(vaddr, src, 2, slot);
41846ef47e2STaylor Simpson }
41946ef47e2STaylor Simpson 
420661ad999STaylor Simpson static inline void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, int slot)
42146ef47e2STaylor Simpson {
42223803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
423661ad999STaylor Simpson     gen_store2(cpu_env, vaddr, tmp, slot);
42446ef47e2STaylor Simpson }
42546ef47e2STaylor Simpson 
426661ad999STaylor Simpson static inline void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, int slot)
42746ef47e2STaylor Simpson {
42846ef47e2STaylor Simpson     gen_store32(vaddr, src, 4, slot);
42946ef47e2STaylor Simpson }
43046ef47e2STaylor Simpson 
431661ad999STaylor Simpson static inline void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, int slot)
43246ef47e2STaylor Simpson {
43323803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
434661ad999STaylor Simpson     gen_store4(cpu_env, vaddr, tmp, slot);
43546ef47e2STaylor Simpson }
43646ef47e2STaylor Simpson 
437661ad999STaylor Simpson static inline void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, int slot)
43846ef47e2STaylor Simpson {
43946ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
44046ef47e2STaylor Simpson     tcg_gen_movi_tl(hex_store_width[slot], 8);
44146ef47e2STaylor Simpson     tcg_gen_mov_i64(hex_store_val64[slot], src);
44246ef47e2STaylor Simpson }
44346ef47e2STaylor Simpson 
444661ad999STaylor Simpson static inline void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, int slot)
44546ef47e2STaylor Simpson {
44623803bbeSPhilippe Mathieu-Daudé     TCGv_i64 tmp = tcg_constant_i64(src);
447661ad999STaylor Simpson     gen_store8(cpu_env, vaddr, tmp, slot);
44846ef47e2STaylor Simpson }
44946ef47e2STaylor Simpson 
45057d352acSTaylor Simpson static TCGv gen_8bitsof(TCGv result, TCGv value)
45157d352acSTaylor Simpson {
45223803bbeSPhilippe Mathieu-Daudé     TCGv zero = tcg_constant_tl(0);
45323803bbeSPhilippe Mathieu-Daudé     TCGv ones = tcg_constant_tl(0xff);
45457d352acSTaylor Simpson     tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero);
45557d352acSTaylor Simpson 
45657d352acSTaylor Simpson     return result;
45757d352acSTaylor Simpson }
45857d352acSTaylor Simpson 
45961c6c06eSTaylor Simpson static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
46061c6c06eSTaylor Simpson                                   TCGCond cond, TCGv pred)
46161c6c06eSTaylor Simpson {
46261c6c06eSTaylor Simpson     TCGLabel *pred_false = NULL;
46361c6c06eSTaylor Simpson     if (cond != TCG_COND_ALWAYS) {
46461c6c06eSTaylor Simpson         pred_false = gen_new_label();
46561c6c06eSTaylor Simpson         tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
46661c6c06eSTaylor Simpson     }
46761c6c06eSTaylor Simpson 
46861c6c06eSTaylor Simpson     if (ctx->pkt->pkt_has_multi_cof) {
46961c6c06eSTaylor Simpson         /* If there are multiple branches in a packet, ignore the second one */
47061c6c06eSTaylor Simpson         tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
47161c6c06eSTaylor Simpson                            hex_branch_taken, tcg_constant_tl(0),
47261c6c06eSTaylor Simpson                            hex_gpr[HEX_REG_PC], addr);
47361c6c06eSTaylor Simpson         tcg_gen_movi_tl(hex_branch_taken, 1);
47461c6c06eSTaylor Simpson     } else {
47561c6c06eSTaylor Simpson         tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
47661c6c06eSTaylor Simpson     }
47761c6c06eSTaylor Simpson 
47861c6c06eSTaylor Simpson     if (cond != TCG_COND_ALWAYS) {
47961c6c06eSTaylor Simpson         gen_set_label(pred_false);
48061c6c06eSTaylor Simpson     }
48161c6c06eSTaylor Simpson }
48261c6c06eSTaylor Simpson 
48361c6c06eSTaylor Simpson static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
48461c6c06eSTaylor Simpson                                    TCGCond cond, TCGv pred)
48561c6c06eSTaylor Simpson {
48661c6c06eSTaylor Simpson     target_ulong dest = ctx->pkt->pc + pc_off;
487*1b9a7f2aSTaylor Simpson     if (ctx->pkt->pkt_has_multi_cof) {
48861c6c06eSTaylor Simpson         gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
489*1b9a7f2aSTaylor Simpson     } else {
490*1b9a7f2aSTaylor Simpson         /* Defer this jump to the end of the TB */
491*1b9a7f2aSTaylor Simpson         ctx->branch_cond = TCG_COND_ALWAYS;
492*1b9a7f2aSTaylor Simpson         if (pred != NULL) {
493*1b9a7f2aSTaylor Simpson             ctx->branch_cond = cond;
494*1b9a7f2aSTaylor Simpson             tcg_gen_mov_tl(hex_branch_taken, pred);
495*1b9a7f2aSTaylor Simpson         }
496*1b9a7f2aSTaylor Simpson         ctx->branch_dest = dest;
497*1b9a7f2aSTaylor Simpson     }
49861c6c06eSTaylor Simpson }
49961c6c06eSTaylor Simpson 
50011b577ffSTaylor Simpson static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
50111b577ffSTaylor Simpson {
50211b577ffSTaylor Simpson     TCGv one = tcg_constant_tl(0xff);
50311b577ffSTaylor Simpson     TCGv zero = tcg_constant_tl(0);
50411b577ffSTaylor Simpson 
50511b577ffSTaylor Simpson     tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
50611b577ffSTaylor Simpson }
50711b577ffSTaylor Simpson 
50897b16fafSTaylor Simpson static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
50997b16fafSTaylor Simpson                            TCGCond cond, TCGv pred)
51097b16fafSTaylor Simpson {
51197b16fafSTaylor Simpson     gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
51297b16fafSTaylor Simpson }
51397b16fafSTaylor Simpson 
51411b577ffSTaylor Simpson static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
51511b577ffSTaylor Simpson                           int pc_off)
51611b577ffSTaylor Simpson {
51711b577ffSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
51811b577ffSTaylor Simpson }
51911b577ffSTaylor Simpson 
52011b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp(DisasContext *ctx,
52111b577ffSTaylor Simpson                               int pnum, TCGCond cond1, TCGv arg1, TCGv arg2,
52211b577ffSTaylor Simpson                               TCGCond cond2, int pc_off)
52311b577ffSTaylor Simpson {
52411b577ffSTaylor Simpson     if (ctx->insn->part1) {
52511b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
52611b577ffSTaylor Simpson         gen_compare(cond1, pred, arg1, arg2);
52711b577ffSTaylor Simpson         gen_log_pred_write(ctx, pnum, pred);
52811b577ffSTaylor Simpson         tcg_temp_free(pred);
52911b577ffSTaylor Simpson     } else {
53011b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
53111b577ffSTaylor Simpson         tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
53211b577ffSTaylor Simpson         gen_cond_jump(ctx, cond2, pred, pc_off);
53311b577ffSTaylor Simpson         tcg_temp_free(pred);
53411b577ffSTaylor Simpson     }
53511b577ffSTaylor Simpson }
53611b577ffSTaylor Simpson 
53711b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
53811b577ffSTaylor Simpson                                 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
53911b577ffSTaylor Simpson                                 int pc_off)
54011b577ffSTaylor Simpson {
54111b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
54211b577ffSTaylor Simpson }
54311b577ffSTaylor Simpson 
54411b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
54511b577ffSTaylor Simpson                                 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
54611b577ffSTaylor Simpson                                 int pc_off)
54711b577ffSTaylor Simpson {
54811b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
54911b577ffSTaylor Simpson }
55011b577ffSTaylor Simpson 
55111b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
55211b577ffSTaylor Simpson                                  int pnum, TCGCond cond, TCGv arg1, int arg2,
55311b577ffSTaylor Simpson                                  int pc_off)
55411b577ffSTaylor Simpson {
55511b577ffSTaylor Simpson     TCGv tmp = tcg_constant_tl(arg2);
55611b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
55711b577ffSTaylor Simpson }
55811b577ffSTaylor Simpson 
55911b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
56011b577ffSTaylor Simpson                                  int pnum, TCGCond cond, TCGv arg1, int arg2,
56111b577ffSTaylor Simpson                                  int pc_off)
56211b577ffSTaylor Simpson {
56311b577ffSTaylor Simpson     TCGv tmp = tcg_constant_tl(arg2);
56411b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
56511b577ffSTaylor Simpson }
56611b577ffSTaylor Simpson 
56711b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
56811b577ffSTaylor Simpson                                    TCGv arg, int pc_off)
56911b577ffSTaylor Simpson {
57011b577ffSTaylor Simpson     gen_cmpnd_cmpi_jmp_t(ctx, pnum, cond, arg, -1, pc_off);
57111b577ffSTaylor Simpson }
57211b577ffSTaylor Simpson 
57311b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_f(DisasContext *ctx, int pnum, TCGCond cond,
57411b577ffSTaylor Simpson                                    TCGv arg, int pc_off)
57511b577ffSTaylor Simpson {
57611b577ffSTaylor Simpson     gen_cmpnd_cmpi_jmp_f(ctx, pnum, cond, arg, -1, pc_off);
57711b577ffSTaylor Simpson }
57811b577ffSTaylor Simpson 
57911b577ffSTaylor Simpson static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
58011b577ffSTaylor Simpson                                   int pnum, TCGv arg, TCGCond cond, int pc_off)
58111b577ffSTaylor Simpson {
58211b577ffSTaylor Simpson     if (ctx->insn->part1) {
58311b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
58411b577ffSTaylor Simpson         tcg_gen_andi_tl(pred, arg, 1);
58511b577ffSTaylor Simpson         gen_8bitsof(pred, pred);
58611b577ffSTaylor Simpson         gen_log_pred_write(ctx, pnum, pred);
58711b577ffSTaylor Simpson         tcg_temp_free(pred);
58811b577ffSTaylor Simpson     } else {
58911b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
59011b577ffSTaylor Simpson         tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
59111b577ffSTaylor Simpson         gen_cond_jump(ctx, cond, pred, pc_off);
59211b577ffSTaylor Simpson         tcg_temp_free(pred);
59311b577ffSTaylor Simpson     }
59411b577ffSTaylor Simpson }
59511b577ffSTaylor Simpson 
59697b16fafSTaylor Simpson static void gen_testbit0_jumpnv(DisasContext *ctx,
59797b16fafSTaylor Simpson                                 TCGv arg, TCGCond cond, int pc_off)
59897b16fafSTaylor Simpson {
59997b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
60097b16fafSTaylor Simpson     tcg_gen_andi_tl(pred, arg, 1);
60197b16fafSTaylor Simpson     gen_cond_jump(ctx, cond, pred, pc_off);
60297b16fafSTaylor Simpson     tcg_temp_free(pred);
60397b16fafSTaylor Simpson }
60497b16fafSTaylor Simpson 
60597b16fafSTaylor Simpson static void gen_jump(DisasContext *ctx, int pc_off)
60697b16fafSTaylor Simpson {
60797b16fafSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
60897b16fafSTaylor Simpson }
60997b16fafSTaylor Simpson 
61097b16fafSTaylor Simpson static void gen_jumpr(DisasContext *ctx, TCGv new_pc)
61197b16fafSTaylor Simpson {
61297b16fafSTaylor Simpson     gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
61397b16fafSTaylor Simpson }
61497b16fafSTaylor Simpson 
61561c6c06eSTaylor Simpson static void gen_call(DisasContext *ctx, int pc_off)
61661c6c06eSTaylor Simpson {
61761c6c06eSTaylor Simpson     TCGv next_PC =
61861c6c06eSTaylor Simpson         tcg_constant_tl(ctx->pkt->pc + ctx->pkt->encod_pkt_size_in_bytes);
61961c6c06eSTaylor Simpson     gen_log_reg_write(HEX_REG_LR, next_PC);
62061c6c06eSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
62161c6c06eSTaylor Simpson }
62261c6c06eSTaylor Simpson 
62361c6c06eSTaylor Simpson static void gen_cond_call(DisasContext *ctx, TCGv pred,
62461c6c06eSTaylor Simpson                           TCGCond cond, int pc_off)
62561c6c06eSTaylor Simpson {
62661c6c06eSTaylor Simpson     TCGv next_PC;
62761c6c06eSTaylor Simpson     TCGv lsb = tcg_temp_local_new();
62861c6c06eSTaylor Simpson     TCGLabel *skip = gen_new_label();
62961c6c06eSTaylor Simpson     tcg_gen_andi_tl(lsb, pred, 1);
63061c6c06eSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
63161c6c06eSTaylor Simpson     tcg_gen_brcondi_tl(cond, lsb, 0, skip);
63261c6c06eSTaylor Simpson     tcg_temp_free(lsb);
63361c6c06eSTaylor Simpson     next_PC =
63461c6c06eSTaylor Simpson         tcg_constant_tl(ctx->pkt->pc + ctx->pkt->encod_pkt_size_in_bytes);
63561c6c06eSTaylor Simpson     gen_log_reg_write(HEX_REG_LR, next_PC);
63661c6c06eSTaylor Simpson     gen_set_label(skip);
63761c6c06eSTaylor Simpson }
63861c6c06eSTaylor Simpson 
63997b16fafSTaylor Simpson static void gen_cmp_jumpnv(DisasContext *ctx,
64097b16fafSTaylor Simpson                            TCGCond cond, TCGv val, TCGv src, int pc_off)
64197b16fafSTaylor Simpson {
64297b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
64397b16fafSTaylor Simpson     tcg_gen_setcond_tl(cond, pred, val, src);
64497b16fafSTaylor Simpson     gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
64597b16fafSTaylor Simpson     tcg_temp_free(pred);
64697b16fafSTaylor Simpson }
64797b16fafSTaylor Simpson 
64897b16fafSTaylor Simpson static void gen_cmpi_jumpnv(DisasContext *ctx,
64997b16fafSTaylor Simpson                             TCGCond cond, TCGv val, int src, int pc_off)
65097b16fafSTaylor Simpson {
65197b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
65297b16fafSTaylor Simpson     tcg_gen_setcondi_tl(cond, pred, val, src);
65397b16fafSTaylor Simpson     gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
65497b16fafSTaylor Simpson     tcg_temp_free(pred);
65597b16fafSTaylor Simpson }
65697b16fafSTaylor Simpson 
6578e8a85c1STaylor Simpson /* Shift left with saturation */
6588e8a85c1STaylor Simpson static void gen_shl_sat(TCGv dst, TCGv src, TCGv shift_amt)
6598e8a85c1STaylor Simpson {
6608e8a85c1STaylor Simpson     TCGv sh32 = tcg_temp_new();
6618e8a85c1STaylor Simpson     TCGv dst_sar = tcg_temp_new();
6628e8a85c1STaylor Simpson     TCGv ovf = tcg_temp_new();
6638e8a85c1STaylor Simpson     TCGv satval = tcg_temp_new();
6648e8a85c1STaylor Simpson     TCGv min = tcg_constant_tl(0x80000000);
6658e8a85c1STaylor Simpson     TCGv max = tcg_constant_tl(0x7fffffff);
6668e8a85c1STaylor Simpson 
6678e8a85c1STaylor Simpson     /*
6688e8a85c1STaylor Simpson      *    Possible values for shift_amt are 0 .. 64
6698e8a85c1STaylor Simpson      *    We need special handling for values above 31
6708e8a85c1STaylor Simpson      *
6718e8a85c1STaylor Simpson      *    sh32 = shift & 31;
6728e8a85c1STaylor Simpson      *    dst = sh32 == shift ? src : 0;
6738e8a85c1STaylor Simpson      *    dst <<= sh32;
6748e8a85c1STaylor Simpson      *    dst_sar = dst >> sh32;
6758e8a85c1STaylor Simpson      *    satval = src < 0 ? min : max;
6768e8a85c1STaylor Simpson      *    if (dst_asr != src) {
6778e8a85c1STaylor Simpson      *        usr.OVF |= 1;
6788e8a85c1STaylor Simpson      *        dst = satval;
6798e8a85c1STaylor Simpson      *    }
6808e8a85c1STaylor Simpson      */
6818e8a85c1STaylor Simpson 
6828e8a85c1STaylor Simpson     tcg_gen_andi_tl(sh32, shift_amt, 31);
6838e8a85c1STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, dst, sh32, shift_amt,
6848e8a85c1STaylor Simpson                        src, tcg_constant_tl(0));
6858e8a85c1STaylor Simpson     tcg_gen_shl_tl(dst, dst, sh32);
6868e8a85c1STaylor Simpson     tcg_gen_sar_tl(dst_sar, dst, sh32);
6878e8a85c1STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
6888e8a85c1STaylor Simpson 
6898e8a85c1STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
6908e8a85c1STaylor Simpson     tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
6918e8a85c1STaylor Simpson     tcg_gen_or_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR], ovf);
6928e8a85c1STaylor Simpson 
6938e8a85c1STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, dst, satval);
6948e8a85c1STaylor Simpson 
6958e8a85c1STaylor Simpson     tcg_temp_free(sh32);
6968e8a85c1STaylor Simpson     tcg_temp_free(dst_sar);
6978e8a85c1STaylor Simpson     tcg_temp_free(ovf);
6988e8a85c1STaylor Simpson     tcg_temp_free(satval);
6998e8a85c1STaylor Simpson }
7008e8a85c1STaylor Simpson 
7018e8a85c1STaylor Simpson static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
7028e8a85c1STaylor Simpson {
7038e8a85c1STaylor Simpson     /*
7048e8a85c1STaylor Simpson      *  Shift arithmetic right
7058e8a85c1STaylor Simpson      *  Robust when shift_amt is >31 bits
7068e8a85c1STaylor Simpson      */
7078e8a85c1STaylor Simpson     TCGv tmp = tcg_temp_new();
7088e8a85c1STaylor Simpson     tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31));
7098e8a85c1STaylor Simpson     tcg_gen_sar_tl(dst, src, tmp);
7108e8a85c1STaylor Simpson     tcg_temp_free(tmp);
7118e8a85c1STaylor Simpson }
7128e8a85c1STaylor Simpson 
7138e8a85c1STaylor Simpson /* Bidirectional shift right with saturation */
7148e8a85c1STaylor Simpson static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
7158e8a85c1STaylor Simpson {
7168e8a85c1STaylor Simpson     TCGv shift_amt = tcg_temp_local_new();
7178e8a85c1STaylor Simpson     TCGLabel *positive = gen_new_label();
7188e8a85c1STaylor Simpson     TCGLabel *done = gen_new_label();
7198e8a85c1STaylor Simpson 
7208e8a85c1STaylor Simpson     tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
7218e8a85c1STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
7228e8a85c1STaylor Simpson 
7238e8a85c1STaylor Simpson     /* Negative shift amount => shift left */
7248e8a85c1STaylor Simpson     tcg_gen_neg_tl(shift_amt, shift_amt);
7258e8a85c1STaylor Simpson     gen_shl_sat(RdV, RsV, shift_amt);
7268e8a85c1STaylor Simpson     tcg_gen_br(done);
7278e8a85c1STaylor Simpson 
7288e8a85c1STaylor Simpson     gen_set_label(positive);
7298e8a85c1STaylor Simpson     /* Positive shift amount => shift right */
7308e8a85c1STaylor Simpson     gen_sar(RdV, RsV, shift_amt);
7318e8a85c1STaylor Simpson 
7328e8a85c1STaylor Simpson     gen_set_label(done);
7338e8a85c1STaylor Simpson 
7348e8a85c1STaylor Simpson     tcg_temp_free(shift_amt);
7358e8a85c1STaylor Simpson }
7368e8a85c1STaylor Simpson 
7378e8a85c1STaylor Simpson /* Bidirectional shift left with saturation */
7388e8a85c1STaylor Simpson static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
7398e8a85c1STaylor Simpson {
7408e8a85c1STaylor Simpson     TCGv shift_amt = tcg_temp_local_new();
7418e8a85c1STaylor Simpson     TCGLabel *positive = gen_new_label();
7428e8a85c1STaylor Simpson     TCGLabel *done = gen_new_label();
7438e8a85c1STaylor Simpson 
7448e8a85c1STaylor Simpson     tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
7458e8a85c1STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
7468e8a85c1STaylor Simpson 
7478e8a85c1STaylor Simpson     /* Negative shift amount => shift right */
7488e8a85c1STaylor Simpson     tcg_gen_neg_tl(shift_amt, shift_amt);
7498e8a85c1STaylor Simpson     gen_sar(RdV, RsV, shift_amt);
7508e8a85c1STaylor Simpson     tcg_gen_br(done);
7518e8a85c1STaylor Simpson 
7528e8a85c1STaylor Simpson     gen_set_label(positive);
7538e8a85c1STaylor Simpson     /* Positive shift amount => shift left */
7548e8a85c1STaylor Simpson     gen_shl_sat(RdV, RsV, shift_amt);
7558e8a85c1STaylor Simpson 
7568e8a85c1STaylor Simpson     gen_set_label(done);
7578e8a85c1STaylor Simpson 
7588e8a85c1STaylor Simpson     tcg_temp_free(shift_amt);
7598e8a85c1STaylor Simpson }
7608e8a85c1STaylor Simpson 
761887d61b2STaylor Simpson static intptr_t vreg_src_off(DisasContext *ctx, int num)
762887d61b2STaylor Simpson {
763887d61b2STaylor Simpson     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
764887d61b2STaylor Simpson 
765887d61b2STaylor Simpson     if (test_bit(num, ctx->vregs_select)) {
766887d61b2STaylor Simpson         offset = ctx_future_vreg_off(ctx, num, 1, false);
767887d61b2STaylor Simpson     }
768887d61b2STaylor Simpson     if (test_bit(num, ctx->vregs_updated_tmp)) {
769887d61b2STaylor Simpson         offset = ctx_tmp_vreg_off(ctx, num, 1, false);
770887d61b2STaylor Simpson     }
771887d61b2STaylor Simpson     return offset;
772887d61b2STaylor Simpson }
773887d61b2STaylor Simpson 
774887d61b2STaylor Simpson static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
775887d61b2STaylor Simpson                                VRegWriteType type, int slot_num,
776887d61b2STaylor Simpson                                bool is_predicated)
777887d61b2STaylor Simpson {
778887d61b2STaylor Simpson     TCGLabel *label_end = NULL;
779887d61b2STaylor Simpson     intptr_t dstoff;
780887d61b2STaylor Simpson 
781887d61b2STaylor Simpson     if (is_predicated) {
782887d61b2STaylor Simpson         TCGv cancelled = tcg_temp_local_new();
783887d61b2STaylor Simpson         label_end = gen_new_label();
784887d61b2STaylor Simpson 
785887d61b2STaylor Simpson         /* Don't do anything if the slot was cancelled */
786887d61b2STaylor Simpson         tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
787887d61b2STaylor Simpson         tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
788887d61b2STaylor Simpson         tcg_temp_free(cancelled);
789887d61b2STaylor Simpson     }
790887d61b2STaylor Simpson 
791887d61b2STaylor Simpson     if (type != EXT_TMP) {
792887d61b2STaylor Simpson         dstoff = ctx_future_vreg_off(ctx, num, 1, true);
793887d61b2STaylor Simpson         tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
794887d61b2STaylor Simpson                          sizeof(MMVector), sizeof(MMVector));
795887d61b2STaylor Simpson         tcg_gen_ori_tl(hex_VRegs_updated, hex_VRegs_updated, 1 << num);
796887d61b2STaylor Simpson     } else {
797887d61b2STaylor Simpson         dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
798887d61b2STaylor Simpson         tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
799887d61b2STaylor Simpson                          sizeof(MMVector), sizeof(MMVector));
800887d61b2STaylor Simpson     }
801887d61b2STaylor Simpson 
802887d61b2STaylor Simpson     if (is_predicated) {
803887d61b2STaylor Simpson         gen_set_label(label_end);
804887d61b2STaylor Simpson     }
805887d61b2STaylor Simpson }
806887d61b2STaylor Simpson 
807887d61b2STaylor Simpson static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
808887d61b2STaylor Simpson                                     VRegWriteType type, int slot_num,
809887d61b2STaylor Simpson                                     bool is_predicated)
810887d61b2STaylor Simpson {
811887d61b2STaylor Simpson     gen_log_vreg_write(ctx, srcoff, num ^ 0, type, slot_num, is_predicated);
812887d61b2STaylor Simpson     srcoff += sizeof(MMVector);
813887d61b2STaylor Simpson     gen_log_vreg_write(ctx, srcoff, num ^ 1, type, slot_num, is_predicated);
814887d61b2STaylor Simpson }
815887d61b2STaylor Simpson 
816887d61b2STaylor Simpson static void gen_log_qreg_write(intptr_t srcoff, int num, int vnew,
817887d61b2STaylor Simpson                                int slot_num, bool is_predicated)
818887d61b2STaylor Simpson {
819887d61b2STaylor Simpson     TCGLabel *label_end = NULL;
820887d61b2STaylor Simpson     intptr_t dstoff;
821887d61b2STaylor Simpson 
822887d61b2STaylor Simpson     if (is_predicated) {
823887d61b2STaylor Simpson         TCGv cancelled = tcg_temp_local_new();
824887d61b2STaylor Simpson         label_end = gen_new_label();
825887d61b2STaylor Simpson 
826887d61b2STaylor Simpson         /* Don't do anything if the slot was cancelled */
827887d61b2STaylor Simpson         tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
828887d61b2STaylor Simpson         tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
829887d61b2STaylor Simpson         tcg_temp_free(cancelled);
830887d61b2STaylor Simpson     }
831887d61b2STaylor Simpson 
832887d61b2STaylor Simpson     dstoff = offsetof(CPUHexagonState, future_QRegs[num]);
833887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMQReg), sizeof(MMQReg));
834887d61b2STaylor Simpson 
835887d61b2STaylor Simpson     if (is_predicated) {
836887d61b2STaylor Simpson         tcg_gen_ori_tl(hex_QRegs_updated, hex_QRegs_updated, 1 << num);
837887d61b2STaylor Simpson         gen_set_label(label_end);
838887d61b2STaylor Simpson     }
839887d61b2STaylor Simpson }
840887d61b2STaylor Simpson 
841887d61b2STaylor Simpson static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
842887d61b2STaylor Simpson                           bool aligned)
843887d61b2STaylor Simpson {
844887d61b2STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
845887d61b2STaylor Simpson     if (aligned) {
846887d61b2STaylor Simpson         tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1));
847887d61b2STaylor Simpson     }
848887d61b2STaylor Simpson     for (int i = 0; i < sizeof(MMVector) / 8; i++) {
849887d61b2STaylor Simpson         tcg_gen_qemu_ld64(tmp, src, ctx->mem_idx);
850887d61b2STaylor Simpson         tcg_gen_addi_tl(src, src, 8);
851887d61b2STaylor Simpson         tcg_gen_st_i64(tmp, cpu_env, dstoff + i * 8);
852887d61b2STaylor Simpson     }
853887d61b2STaylor Simpson     tcg_temp_free_i64(tmp);
854887d61b2STaylor Simpson }
855887d61b2STaylor Simpson 
8561e536334STaylor Simpson static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
8571e536334STaylor Simpson                            int slot, bool aligned)
858887d61b2STaylor Simpson {
859887d61b2STaylor Simpson     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
860887d61b2STaylor Simpson     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
861887d61b2STaylor Simpson 
8621e536334STaylor Simpson     if (is_gather_store_insn(ctx)) {
863887d61b2STaylor Simpson         TCGv sl = tcg_constant_tl(slot);
864887d61b2STaylor Simpson         gen_helper_gather_store(cpu_env, EA, sl);
865887d61b2STaylor Simpson         return;
866887d61b2STaylor Simpson     }
867887d61b2STaylor Simpson 
868887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
869887d61b2STaylor Simpson     if (aligned) {
870887d61b2STaylor Simpson         tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
871887d61b2STaylor Simpson                         ~((int32_t)sizeof(MMVector) - 1));
872887d61b2STaylor Simpson     } else {
873887d61b2STaylor Simpson         tcg_gen_mov_tl(hex_vstore_addr[slot], EA);
874887d61b2STaylor Simpson     }
875887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
876887d61b2STaylor Simpson 
877887d61b2STaylor Simpson     /* Copy the data to the vstore buffer */
878887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
879887d61b2STaylor Simpson     /* Set the mask to all 1's */
880887d61b2STaylor Simpson     tcg_gen_gvec_dup_imm(MO_64, maskoff, sizeof(MMQReg), sizeof(MMQReg), ~0LL);
881887d61b2STaylor Simpson }
882887d61b2STaylor Simpson 
883887d61b2STaylor Simpson static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
884887d61b2STaylor Simpson                                   intptr_t bitsoff, int slot, bool invert)
885887d61b2STaylor Simpson {
886887d61b2STaylor Simpson     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
887887d61b2STaylor Simpson     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
888887d61b2STaylor Simpson 
889887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
890887d61b2STaylor Simpson     tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
891887d61b2STaylor Simpson                     ~((int32_t)sizeof(MMVector) - 1));
892887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
893887d61b2STaylor Simpson 
894887d61b2STaylor Simpson     /* Copy the data to the vstore buffer */
895887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
896887d61b2STaylor Simpson     /* Copy the mask */
897887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, maskoff, bitsoff, sizeof(MMQReg), sizeof(MMQReg));
898887d61b2STaylor Simpson     if (invert) {
899887d61b2STaylor Simpson         tcg_gen_gvec_not(MO_64, maskoff, maskoff,
900887d61b2STaylor Simpson                          sizeof(MMQReg), sizeof(MMQReg));
901887d61b2STaylor Simpson     }
902887d61b2STaylor Simpson }
903887d61b2STaylor Simpson 
904887d61b2STaylor Simpson static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
905887d61b2STaylor Simpson {
906887d61b2STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
907887d61b2STaylor Simpson     TCGv_i64 word = tcg_temp_new_i64();
908887d61b2STaylor Simpson     TCGv_i64 bits = tcg_temp_new_i64();
909887d61b2STaylor Simpson     TCGv_i64 mask = tcg_temp_new_i64();
910887d61b2STaylor Simpson     TCGv_i64 zero = tcg_constant_i64(0);
911887d61b2STaylor Simpson     TCGv_i64 ones = tcg_constant_i64(~0);
912887d61b2STaylor Simpson 
913887d61b2STaylor Simpson     for (int i = 0; i < sizeof(MMVector) / 8; i++) {
914887d61b2STaylor Simpson         tcg_gen_ld_i64(tmp, cpu_env, srcoff + i * 8);
915887d61b2STaylor Simpson         tcg_gen_movi_i64(mask, 0);
916887d61b2STaylor Simpson 
917887d61b2STaylor Simpson         for (int j = 0; j < 8; j += size) {
918887d61b2STaylor Simpson             tcg_gen_extract_i64(word, tmp, j * 8, size * 8);
919887d61b2STaylor Simpson             tcg_gen_movcond_i64(TCG_COND_NE, bits, word, zero, ones, zero);
920887d61b2STaylor Simpson             tcg_gen_deposit_i64(mask, mask, bits, j, size);
921887d61b2STaylor Simpson         }
922887d61b2STaylor Simpson 
923887d61b2STaylor Simpson         tcg_gen_st8_i64(mask, cpu_env, dstoff + i);
924887d61b2STaylor Simpson     }
925887d61b2STaylor Simpson     tcg_temp_free_i64(tmp);
926887d61b2STaylor Simpson     tcg_temp_free_i64(word);
927887d61b2STaylor Simpson     tcg_temp_free_i64(bits);
928887d61b2STaylor Simpson     tcg_temp_free_i64(mask);
929887d61b2STaylor Simpson }
930887d61b2STaylor Simpson 
93115fc6badSTaylor Simpson static void probe_noshuf_load(TCGv va, int s, int mi)
93215fc6badSTaylor Simpson {
93315fc6badSTaylor Simpson     TCGv size = tcg_constant_tl(s);
93415fc6badSTaylor Simpson     TCGv mem_idx = tcg_constant_tl(mi);
93515fc6badSTaylor Simpson     gen_helper_probe_noshuf_load(cpu_env, va, size, mem_idx);
93615fc6badSTaylor Simpson }
93715fc6badSTaylor Simpson 
93857acfcdeSTaylor Simpson #include "tcg_funcs_generated.c.inc"
93957acfcdeSTaylor Simpson #include "tcg_func_table_generated.c.inc"
940