xref: /openbmc/qemu/target/hexagon/genptr.c (revision ad75a51e)
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"
2313e27d1fSRichard Henderson #include "exec/helper-gen.h"
2457acfcdeSTaylor Simpson #include "insn.h"
2557acfcdeSTaylor Simpson #include "opcodes.h"
2657acfcdeSTaylor Simpson #include "translate.h"
27a33872ebSTaylor Simpson #define QEMU_GENERATE       /* Used internally by macros.h */
2857acfcdeSTaylor Simpson #include "macros.h"
29887d61b2STaylor Simpson #include "mmvec/macros.h"
30a33872ebSTaylor Simpson #undef QEMU_GENERATE
3157acfcdeSTaylor Simpson #include "gen_tcg.h"
32d51bcabeSTaylor Simpson #include "gen_tcg_hvx.h"
337e8b3b39SPaolo Montesel #include "genptr.h"
347e8b3b39SPaolo Montesel 
gen_read_reg(TCGv result,int num)3542659e04SNiccolò Izzo TCGv gen_read_reg(TCGv result, int num)
3642659e04SNiccolò Izzo {
3742659e04SNiccolò Izzo     tcg_gen_mov_tl(result, hex_gpr[num]);
3842659e04SNiccolò Izzo     return result;
3942659e04SNiccolò Izzo }
4042659e04SNiccolò Izzo 
gen_read_preg(TCGv pred,uint8_t num)417e8b3b39SPaolo Montesel TCGv gen_read_preg(TCGv pred, uint8_t num)
427e8b3b39SPaolo Montesel {
437e8b3b39SPaolo Montesel     tcg_gen_mov_tl(pred, hex_pred[num]);
447e8b3b39SPaolo Montesel     return pred;
457e8b3b39SPaolo Montesel }
4657acfcdeSTaylor Simpson 
47d63aeb3bSMarco Liebel #define IMMUTABLE (~0)
48d63aeb3bSMarco Liebel 
49d54c5615STaylor Simpson const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = {
50d63aeb3bSMarco Liebel     [HEX_REG_USR] = 0xc13000c0,
51d63aeb3bSMarco Liebel     [HEX_REG_PC] = IMMUTABLE,
52d63aeb3bSMarco Liebel     [HEX_REG_GP] = 0x3f,
53d63aeb3bSMarco Liebel     [HEX_REG_UPCYCLELO] = IMMUTABLE,
54d63aeb3bSMarco Liebel     [HEX_REG_UPCYCLEHI] = IMMUTABLE,
55d63aeb3bSMarco Liebel     [HEX_REG_UTIMERLO] = IMMUTABLE,
56d63aeb3bSMarco Liebel     [HEX_REG_UTIMERHI] = IMMUTABLE,
57d63aeb3bSMarco Liebel };
58d63aeb3bSMarco Liebel 
gen_masked_reg_write(TCGv new_val,TCGv cur_val,target_ulong reg_mask)59d63aeb3bSMarco Liebel static inline void gen_masked_reg_write(TCGv new_val, TCGv cur_val,
60d63aeb3bSMarco Liebel                                         target_ulong reg_mask)
61d63aeb3bSMarco Liebel {
62d63aeb3bSMarco Liebel     if (reg_mask) {
63d63aeb3bSMarco Liebel         TCGv tmp = tcg_temp_new();
64d63aeb3bSMarco Liebel 
65d63aeb3bSMarco Liebel         /* new_val = (new_val & ~reg_mask) | (cur_val & reg_mask) */
66d63aeb3bSMarco Liebel         tcg_gen_andi_tl(new_val, new_val, ~reg_mask);
67d63aeb3bSMarco Liebel         tcg_gen_andi_tl(tmp, cur_val, reg_mask);
68d63aeb3bSMarco Liebel         tcg_gen_or_tl(new_val, new_val, tmp);
69d63aeb3bSMarco Liebel     }
70d63aeb3bSMarco Liebel }
71d63aeb3bSMarco Liebel 
get_result_gpr(DisasContext * ctx,int rnum)726aa4f1d1STaylor Simpson TCGv get_result_gpr(DisasContext *ctx, int rnum)
7357acfcdeSTaylor Simpson {
74d54c5615STaylor Simpson     if (ctx->need_commit) {
756aa4f1d1STaylor Simpson         if (rnum == HEX_REG_USR) {
766aa4f1d1STaylor Simpson             return hex_new_value_usr;
776aa4f1d1STaylor Simpson         } else {
784ff56764STaylor Simpson             if (ctx->new_value[rnum] == NULL) {
794ff56764STaylor Simpson                 ctx->new_value[rnum] = tcg_temp_new();
804ff56764STaylor Simpson                 tcg_gen_movi_tl(ctx->new_value[rnum], 0);
814ff56764STaylor Simpson             }
824ff56764STaylor Simpson             return ctx->new_value[rnum];
836aa4f1d1STaylor Simpson         }
84d54c5615STaylor Simpson     } else {
85d54c5615STaylor Simpson         return hex_gpr[rnum];
86d54c5615STaylor Simpson     }
8785580a65STaylor Simpson }
88e28b77a6STaylor Simpson 
get_result_gpr_pair(DisasContext * ctx,int rnum)89e28b77a6STaylor Simpson static TCGv_i64 get_result_gpr_pair(DisasContext *ctx, int rnum)
90e28b77a6STaylor Simpson {
91e28b77a6STaylor Simpson     TCGv_i64 result = tcg_temp_new_i64();
92d54c5615STaylor Simpson     tcg_gen_concat_i32_i64(result, get_result_gpr(ctx, rnum),
93d54c5615STaylor Simpson                                    get_result_gpr(ctx, rnum + 1));
94e28b77a6STaylor Simpson     return result;
9557acfcdeSTaylor Simpson }
9657acfcdeSTaylor Simpson 
gen_log_reg_write(DisasContext * ctx,int rnum,TCGv val)9707540a28STaylor Simpson void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val)
9857acfcdeSTaylor Simpson {
99d63aeb3bSMarco Liebel     const target_ulong reg_mask = reg_immut_masks[rnum];
100d63aeb3bSMarco Liebel 
101d63aeb3bSMarco Liebel     gen_masked_reg_write(val, hex_gpr[rnum], reg_mask);
102d54c5615STaylor Simpson     tcg_gen_mov_tl(get_result_gpr(ctx, rnum), val);
10385580a65STaylor Simpson     if (HEX_DEBUG) {
10457acfcdeSTaylor Simpson         /* Do this so HELPER(debug_commit_end) will know */
10557acfcdeSTaylor Simpson         tcg_gen_movi_tl(hex_reg_written[rnum], 1);
10685580a65STaylor Simpson     }
10757acfcdeSTaylor Simpson }
10857acfcdeSTaylor Simpson 
gen_log_reg_write_pair(DisasContext * ctx,int rnum,TCGv_i64 val)10907540a28STaylor Simpson static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
11057acfcdeSTaylor Simpson {
111d63aeb3bSMarco Liebel     TCGv val32 = tcg_temp_new();
112d63aeb3bSMarco Liebel 
11357acfcdeSTaylor Simpson     /* Low word */
114d63aeb3bSMarco Liebel     tcg_gen_extrl_i64_i32(val32, val);
115d54c5615STaylor Simpson     gen_log_reg_write(ctx, rnum, val32);
11657acfcdeSTaylor Simpson 
11757acfcdeSTaylor Simpson     /* High word */
118d63aeb3bSMarco Liebel     tcg_gen_extrh_i64_i32(val32, val);
119d54c5615STaylor Simpson     gen_log_reg_write(ctx, rnum + 1, val32);
12057acfcdeSTaylor Simpson }
12157acfcdeSTaylor Simpson 
get_result_pred(DisasContext * ctx,int pnum)122455e169dSTaylor Simpson TCGv get_result_pred(DisasContext *ctx, int pnum)
123455e169dSTaylor Simpson {
124455e169dSTaylor Simpson     if (ctx->need_commit) {
125e22edc7cSTaylor Simpson         if (ctx->new_pred_value[pnum] == NULL) {
126e22edc7cSTaylor Simpson             ctx->new_pred_value[pnum] = tcg_temp_new();
127e22edc7cSTaylor Simpson             tcg_gen_movi_tl(ctx->new_pred_value[pnum], 0);
128e22edc7cSTaylor Simpson         }
129e22edc7cSTaylor Simpson         return ctx->new_pred_value[pnum];
130455e169dSTaylor Simpson     } else {
131455e169dSTaylor Simpson         return hex_pred[pnum];
132455e169dSTaylor Simpson     }
133455e169dSTaylor Simpson }
134455e169dSTaylor Simpson 
gen_log_pred_write(DisasContext * ctx,int pnum,TCGv val)1357e8b3b39SPaolo Montesel void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
13657acfcdeSTaylor Simpson {
137455e169dSTaylor Simpson     TCGv pred = get_result_pred(ctx, pnum);
13857acfcdeSTaylor Simpson     TCGv base_val = tcg_temp_new();
13957acfcdeSTaylor Simpson 
14057acfcdeSTaylor Simpson     tcg_gen_andi_tl(base_val, val, 0xff);
1416c677c60STaylor Simpson 
1426c677c60STaylor Simpson     /*
1436c677c60STaylor Simpson      * Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual
1446c677c60STaylor Simpson      *
1456c677c60STaylor Simpson      * Multiple writes to the same preg are and'ed together
1466c677c60STaylor Simpson      * If this is the first predicate write in the packet, do a
1476c677c60STaylor Simpson      * straight assignment.  Otherwise, do an and.
1486c677c60STaylor Simpson      */
1496c677c60STaylor Simpson     if (!test_bit(pnum, ctx->pregs_written)) {
150455e169dSTaylor Simpson         tcg_gen_mov_tl(pred, base_val);
1516c677c60STaylor Simpson     } else {
152455e169dSTaylor Simpson         tcg_gen_and_tl(pred, pred, base_val);
1536c677c60STaylor Simpson     }
15425e1d87dSTaylor Simpson     if (HEX_DEBUG) {
155842b206fSTaylor Simpson         tcg_gen_ori_tl(ctx->pred_written, ctx->pred_written, 1 << pnum);
15625e1d87dSTaylor Simpson     }
15710849c26STaylor Simpson     set_bit(pnum, ctx->pregs_written);
15857acfcdeSTaylor Simpson }
15957acfcdeSTaylor Simpson 
gen_read_p3_0(TCGv control_reg)16057acfcdeSTaylor Simpson static inline void gen_read_p3_0(TCGv control_reg)
16157acfcdeSTaylor Simpson {
16257acfcdeSTaylor Simpson     tcg_gen_movi_tl(control_reg, 0);
16357acfcdeSTaylor Simpson     for (int i = 0; i < NUM_PREGS; i++) {
16457acfcdeSTaylor Simpson         tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8);
16557acfcdeSTaylor Simpson     }
16657acfcdeSTaylor Simpson }
16757acfcdeSTaylor Simpson 
16857acfcdeSTaylor Simpson /*
16957acfcdeSTaylor Simpson  * Certain control registers require special handling on read
17072895676SMukilan Thiyagarajan  *     HEX_REG_P3_0_ALIASED  aliased to the predicate registers
17157acfcdeSTaylor Simpson  *                           -> concat the 4 predicate registers together
17257acfcdeSTaylor Simpson  *     HEX_REG_PC            actual value stored in DisasContext
17357acfcdeSTaylor Simpson  *                           -> assign from ctx->base.pc_next
17457acfcdeSTaylor Simpson  *     HEX_REG_QEMU_*_CNT    changes in current TB in DisasContext
17557acfcdeSTaylor Simpson  *                           -> add current TB changes to existing reg value
17657acfcdeSTaylor Simpson  */
gen_read_ctrl_reg(DisasContext * ctx,const int reg_num,TCGv dest)17757acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
17857acfcdeSTaylor Simpson                                      TCGv dest)
17957acfcdeSTaylor Simpson {
18072895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
18157acfcdeSTaylor Simpson         gen_read_p3_0(dest);
18257acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_PC) {
18357acfcdeSTaylor Simpson         tcg_gen_movi_tl(dest, ctx->base.pc_next);
18457acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
18557acfcdeSTaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT],
18657acfcdeSTaylor Simpson                         ctx->num_packets);
18757acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_INSN_CNT) {
18857acfcdeSTaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT],
18957acfcdeSTaylor Simpson                         ctx->num_insns);
190a82dd548STaylor Simpson     } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
191a82dd548STaylor Simpson         tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_HVX_CNT],
192a82dd548STaylor Simpson                         ctx->num_hvx_insns);
19357acfcdeSTaylor Simpson     } else {
19457acfcdeSTaylor Simpson         tcg_gen_mov_tl(dest, hex_gpr[reg_num]);
19557acfcdeSTaylor Simpson     }
19657acfcdeSTaylor Simpson }
19757acfcdeSTaylor Simpson 
gen_read_ctrl_reg_pair(DisasContext * ctx,const int reg_num,TCGv_i64 dest)19857acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
19957acfcdeSTaylor Simpson                                           TCGv_i64 dest)
20057acfcdeSTaylor Simpson {
20172895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
20257acfcdeSTaylor Simpson         TCGv p3_0 = tcg_temp_new();
20357acfcdeSTaylor Simpson         gen_read_p3_0(p3_0);
20457acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
20557acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_PC - 1) {
20623803bbeSPhilippe Mathieu-Daudé         TCGv pc = tcg_constant_tl(ctx->base.pc_next);
20757acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc);
20857acfcdeSTaylor Simpson     } else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
20957acfcdeSTaylor Simpson         TCGv pkt_cnt = tcg_temp_new();
21057acfcdeSTaylor Simpson         TCGv insn_cnt = tcg_temp_new();
21157acfcdeSTaylor Simpson         tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT],
21257acfcdeSTaylor Simpson                         ctx->num_packets);
21357acfcdeSTaylor Simpson         tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT],
21457acfcdeSTaylor Simpson                         ctx->num_insns);
21557acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt);
216a82dd548STaylor Simpson     } else if (reg_num == HEX_REG_QEMU_HVX_CNT) {
217a82dd548STaylor Simpson         TCGv hvx_cnt = tcg_temp_new();
218a82dd548STaylor Simpson         tcg_gen_addi_tl(hvx_cnt, hex_gpr[HEX_REG_QEMU_HVX_CNT],
219a82dd548STaylor Simpson                         ctx->num_hvx_insns);
220a82dd548STaylor Simpson         tcg_gen_concat_i32_i64(dest, hvx_cnt, hex_gpr[reg_num + 1]);
22157acfcdeSTaylor Simpson     } else {
22257acfcdeSTaylor Simpson         tcg_gen_concat_i32_i64(dest,
22357acfcdeSTaylor Simpson             hex_gpr[reg_num],
22457acfcdeSTaylor Simpson             hex_gpr[reg_num + 1]);
22557acfcdeSTaylor Simpson     }
22657acfcdeSTaylor Simpson }
22757acfcdeSTaylor Simpson 
gen_write_p3_0(DisasContext * ctx,TCGv control_reg)228c0d86060STaylor Simpson static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg)
22957acfcdeSTaylor Simpson {
230c0d86060STaylor Simpson     TCGv hex_p8 = tcg_temp_new();
23157acfcdeSTaylor Simpson     for (int i = 0; i < NUM_PREGS; i++) {
232c0d86060STaylor Simpson         tcg_gen_extract_tl(hex_p8, control_reg, i * 8, 8);
233c0d86060STaylor Simpson         gen_log_pred_write(ctx, i, hex_p8);
23457acfcdeSTaylor Simpson     }
23557acfcdeSTaylor Simpson }
23657acfcdeSTaylor Simpson 
23757acfcdeSTaylor Simpson /*
23857acfcdeSTaylor Simpson  * Certain control registers require special handling on write
23972895676SMukilan Thiyagarajan  *     HEX_REG_P3_0_ALIASED  aliased to the predicate registers
24057acfcdeSTaylor Simpson  *                           -> break the value across 4 predicate registers
24157acfcdeSTaylor Simpson  *     HEX_REG_QEMU_*_CNT    changes in current TB in DisasContext
24257acfcdeSTaylor Simpson  *                            -> clear the changes
24357acfcdeSTaylor Simpson  */
gen_write_ctrl_reg(DisasContext * ctx,int reg_num,TCGv val)24457acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
24557acfcdeSTaylor Simpson                                       TCGv val)
24657acfcdeSTaylor Simpson {
24772895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
248c0d86060STaylor Simpson         gen_write_p3_0(ctx, val);
24957acfcdeSTaylor Simpson     } else {
25007540a28STaylor Simpson         gen_log_reg_write(ctx, reg_num, val);
25157acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_PKT_CNT) {
25257acfcdeSTaylor Simpson             ctx->num_packets = 0;
25357acfcdeSTaylor Simpson         }
25457acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_INSN_CNT) {
25557acfcdeSTaylor Simpson             ctx->num_insns = 0;
25657acfcdeSTaylor Simpson         }
257a82dd548STaylor Simpson         if (reg_num == HEX_REG_QEMU_HVX_CNT) {
258a82dd548STaylor Simpson             ctx->num_hvx_insns = 0;
259a82dd548STaylor Simpson         }
26057acfcdeSTaylor Simpson     }
26157acfcdeSTaylor Simpson }
26257acfcdeSTaylor Simpson 
gen_write_ctrl_reg_pair(DisasContext * ctx,int reg_num,TCGv_i64 val)26357acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
26457acfcdeSTaylor Simpson                                            TCGv_i64 val)
26557acfcdeSTaylor Simpson {
26672895676SMukilan Thiyagarajan     if (reg_num == HEX_REG_P3_0_ALIASED) {
267e28b77a6STaylor Simpson         TCGv result = get_result_gpr(ctx, reg_num + 1);
26857acfcdeSTaylor Simpson         TCGv val32 = tcg_temp_new();
26957acfcdeSTaylor Simpson         tcg_gen_extrl_i64_i32(val32, val);
270c0d86060STaylor Simpson         gen_write_p3_0(ctx, val32);
27157acfcdeSTaylor Simpson         tcg_gen_extrh_i64_i32(val32, val);
272e28b77a6STaylor Simpson         tcg_gen_mov_tl(result, val32);
27357acfcdeSTaylor Simpson     } else {
27407540a28STaylor Simpson         gen_log_reg_write_pair(ctx, reg_num, val);
27557acfcdeSTaylor Simpson         if (reg_num == HEX_REG_QEMU_PKT_CNT) {
27657acfcdeSTaylor Simpson             ctx->num_packets = 0;
27757acfcdeSTaylor Simpson             ctx->num_insns = 0;
27857acfcdeSTaylor Simpson         }
279a82dd548STaylor Simpson         if (reg_num == HEX_REG_QEMU_HVX_CNT) {
280a82dd548STaylor Simpson             ctx->num_hvx_insns = 0;
281a82dd548STaylor Simpson         }
28257acfcdeSTaylor Simpson     }
28357acfcdeSTaylor Simpson }
28457acfcdeSTaylor Simpson 
gen_get_byte(TCGv result,int N,TCGv src,bool sign)2857e8b3b39SPaolo Montesel TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign)
28646ef47e2STaylor Simpson {
28746ef47e2STaylor Simpson     if (sign) {
28846ef47e2STaylor Simpson         tcg_gen_sextract_tl(result, src, N * 8, 8);
28946ef47e2STaylor Simpson     } else {
29046ef47e2STaylor Simpson         tcg_gen_extract_tl(result, src, N * 8, 8);
29146ef47e2STaylor Simpson     }
29246ef47e2STaylor Simpson     return result;
29346ef47e2STaylor Simpson }
29446ef47e2STaylor Simpson 
gen_get_byte_i64(TCGv result,int N,TCGv_i64 src,bool sign)2957e8b3b39SPaolo Montesel TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign)
2960a65d286STaylor Simpson {
2970a65d286STaylor Simpson     TCGv_i64 res64 = tcg_temp_new_i64();
2980a65d286STaylor Simpson     if (sign) {
2990a65d286STaylor Simpson         tcg_gen_sextract_i64(res64, src, N * 8, 8);
3000a65d286STaylor Simpson     } else {
3010a65d286STaylor Simpson         tcg_gen_extract_i64(res64, src, N * 8, 8);
3020a65d286STaylor Simpson     }
3030a65d286STaylor Simpson     tcg_gen_extrl_i64_i32(result, res64);
3040a65d286STaylor Simpson 
3050a65d286STaylor Simpson     return result;
3060a65d286STaylor Simpson }
3070a65d286STaylor Simpson 
gen_get_half(TCGv result,int N,TCGv src,bool sign)3087e8b3b39SPaolo Montesel TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign)
30946ef47e2STaylor Simpson {
31046ef47e2STaylor Simpson     if (sign) {
31146ef47e2STaylor Simpson         tcg_gen_sextract_tl(result, src, N * 16, 16);
31246ef47e2STaylor Simpson     } else {
31346ef47e2STaylor Simpson         tcg_gen_extract_tl(result, src, N * 16, 16);
31446ef47e2STaylor Simpson     }
31546ef47e2STaylor Simpson     return result;
31646ef47e2STaylor Simpson }
31746ef47e2STaylor Simpson 
gen_set_half(int N,TCGv result,TCGv src)3187e8b3b39SPaolo Montesel void gen_set_half(int N, TCGv result, TCGv src)
3190d0b91a8STaylor Simpson {
3200d0b91a8STaylor Simpson     tcg_gen_deposit_tl(result, result, src, N * 16, 16);
3210d0b91a8STaylor Simpson }
3220d0b91a8STaylor Simpson 
gen_set_half_i64(int N,TCGv_i64 result,TCGv src)3237e8b3b39SPaolo Montesel void gen_set_half_i64(int N, TCGv_i64 result, TCGv src)
3240d0b91a8STaylor Simpson {
3250d0b91a8STaylor Simpson     TCGv_i64 src64 = tcg_temp_new_i64();
3260d0b91a8STaylor Simpson     tcg_gen_extu_i32_i64(src64, src);
3270d0b91a8STaylor Simpson     tcg_gen_deposit_i64(result, result, src64, N * 16, 16);
3280d0b91a8STaylor Simpson }
3290d0b91a8STaylor Simpson 
gen_set_byte_i64(int N,TCGv_i64 result,TCGv src)3307e8b3b39SPaolo Montesel void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src)
3310a65d286STaylor Simpson {
3320a65d286STaylor Simpson     TCGv_i64 src64 = tcg_temp_new_i64();
3330a65d286STaylor Simpson     tcg_gen_extu_i32_i64(src64, src);
3340a65d286STaylor Simpson     tcg_gen_deposit_i64(result, result, src64, N * 8, 8);
3350a65d286STaylor Simpson }
3360a65d286STaylor Simpson 
gen_load_locked4u(TCGv dest,TCGv vaddr,int mem_index)33757acfcdeSTaylor Simpson static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index)
33857acfcdeSTaylor Simpson {
33953b26d25SRichard Henderson     tcg_gen_qemu_ld_tl(dest, vaddr, mem_index, MO_TEUL);
34057acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_addr, vaddr);
34157acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_val, dest);
34257acfcdeSTaylor Simpson }
34357acfcdeSTaylor Simpson 
gen_load_locked8u(TCGv_i64 dest,TCGv vaddr,int mem_index)34457acfcdeSTaylor Simpson static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index)
34557acfcdeSTaylor Simpson {
34653b26d25SRichard Henderson     tcg_gen_qemu_ld_i64(dest, vaddr, mem_index, MO_TEUQ);
34757acfcdeSTaylor Simpson     tcg_gen_mov_tl(hex_llsc_addr, vaddr);
34857acfcdeSTaylor Simpson     tcg_gen_mov_i64(hex_llsc_val_i64, dest);
34957acfcdeSTaylor Simpson }
35057acfcdeSTaylor Simpson 
gen_store_conditional4(DisasContext * ctx,TCGv pred,TCGv vaddr,TCGv src)35188725336STaylor Simpson static inline void gen_store_conditional4(DisasContext *ctx,
35257acfcdeSTaylor Simpson                                           TCGv pred, TCGv vaddr, TCGv src)
35357acfcdeSTaylor Simpson {
35457acfcdeSTaylor Simpson     TCGLabel *fail = gen_new_label();
35557acfcdeSTaylor Simpson     TCGLabel *done = gen_new_label();
35657acfcdeSTaylor Simpson     TCGv one, zero, tmp;
35757acfcdeSTaylor Simpson 
35857acfcdeSTaylor Simpson     tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
35957acfcdeSTaylor Simpson 
36023803bbeSPhilippe Mathieu-Daudé     one = tcg_constant_tl(0xff);
36123803bbeSPhilippe Mathieu-Daudé     zero = tcg_constant_tl(0);
36257acfcdeSTaylor Simpson     tmp = tcg_temp_new();
36357acfcdeSTaylor Simpson     tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src,
36457acfcdeSTaylor Simpson                               ctx->mem_idx, MO_32);
36588725336STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, pred, tmp, hex_llsc_val,
36657acfcdeSTaylor Simpson                        one, zero);
36757acfcdeSTaylor Simpson     tcg_gen_br(done);
36857acfcdeSTaylor Simpson 
36957acfcdeSTaylor Simpson     gen_set_label(fail);
37057acfcdeSTaylor Simpson     tcg_gen_movi_tl(pred, 0);
37157acfcdeSTaylor Simpson 
37257acfcdeSTaylor Simpson     gen_set_label(done);
37357acfcdeSTaylor Simpson     tcg_gen_movi_tl(hex_llsc_addr, ~0);
37457acfcdeSTaylor Simpson }
37557acfcdeSTaylor Simpson 
gen_store_conditional8(DisasContext * ctx,TCGv pred,TCGv vaddr,TCGv_i64 src)37688725336STaylor Simpson static inline void gen_store_conditional8(DisasContext *ctx,
37757acfcdeSTaylor Simpson                                           TCGv pred, TCGv vaddr, TCGv_i64 src)
37857acfcdeSTaylor Simpson {
37957acfcdeSTaylor Simpson     TCGLabel *fail = gen_new_label();
38057acfcdeSTaylor Simpson     TCGLabel *done = gen_new_label();
38157acfcdeSTaylor Simpson     TCGv_i64 one, zero, tmp;
38257acfcdeSTaylor Simpson 
38357acfcdeSTaylor Simpson     tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
38457acfcdeSTaylor Simpson 
38523803bbeSPhilippe Mathieu-Daudé     one = tcg_constant_i64(0xff);
38623803bbeSPhilippe Mathieu-Daudé     zero = tcg_constant_i64(0);
38757acfcdeSTaylor Simpson     tmp = tcg_temp_new_i64();
38857acfcdeSTaylor Simpson     tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src,
38957acfcdeSTaylor Simpson                                ctx->mem_idx, MO_64);
39057acfcdeSTaylor Simpson     tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64,
39157acfcdeSTaylor Simpson                         one, zero);
39288725336STaylor Simpson     tcg_gen_extrl_i64_i32(pred, tmp);
39357acfcdeSTaylor Simpson     tcg_gen_br(done);
39457acfcdeSTaylor Simpson 
39557acfcdeSTaylor Simpson     gen_set_label(fail);
39657acfcdeSTaylor Simpson     tcg_gen_movi_tl(pred, 0);
39757acfcdeSTaylor Simpson 
39857acfcdeSTaylor Simpson     gen_set_label(done);
39957acfcdeSTaylor Simpson     tcg_gen_movi_tl(hex_llsc_addr, ~0);
40057acfcdeSTaylor Simpson }
40157acfcdeSTaylor Simpson 
402e5d0d78dSTaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
gen_slotval(DisasContext * ctx)403e5d0d78dSTaylor Simpson static TCGv gen_slotval(DisasContext *ctx)
404e5d0d78dSTaylor Simpson {
405e5d0d78dSTaylor Simpson     int slotval = (ctx->pkt->pkt_has_store_s1 & 1) | (ctx->insn->slot << 1);
406e5d0d78dSTaylor Simpson     return tcg_constant_tl(slotval);
407e5d0d78dSTaylor Simpson }
408e5d0d78dSTaylor Simpson #endif
409e5d0d78dSTaylor Simpson 
gen_store32(TCGv vaddr,TCGv src,int width,uint32_t slot)4107e8b3b39SPaolo Montesel void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot)
41146ef47e2STaylor Simpson {
41246ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
41346ef47e2STaylor Simpson     tcg_gen_movi_tl(hex_store_width[slot], width);
41446ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_val32[slot], src);
41546ef47e2STaylor Simpson }
41646ef47e2STaylor Simpson 
gen_store1(TCGv_env tcg_env,TCGv vaddr,TCGv src,uint32_t slot)417*ad75a51eSRichard Henderson void gen_store1(TCGv_env tcg_env, TCGv vaddr, TCGv src, uint32_t slot)
41846ef47e2STaylor Simpson {
41946ef47e2STaylor Simpson     gen_store32(vaddr, src, 1, slot);
42046ef47e2STaylor Simpson }
42146ef47e2STaylor Simpson 
gen_store1i(TCGv_env tcg_env,TCGv vaddr,int32_t src,uint32_t slot)422*ad75a51eSRichard Henderson void gen_store1i(TCGv_env tcg_env, TCGv vaddr, int32_t src, uint32_t slot)
42346ef47e2STaylor Simpson {
42423803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
425*ad75a51eSRichard Henderson     gen_store1(tcg_env, vaddr, tmp, slot);
42646ef47e2STaylor Simpson }
42746ef47e2STaylor Simpson 
gen_store2(TCGv_env tcg_env,TCGv vaddr,TCGv src,uint32_t slot)428*ad75a51eSRichard Henderson void gen_store2(TCGv_env tcg_env, TCGv vaddr, TCGv src, uint32_t slot)
42946ef47e2STaylor Simpson {
43046ef47e2STaylor Simpson     gen_store32(vaddr, src, 2, slot);
43146ef47e2STaylor Simpson }
43246ef47e2STaylor Simpson 
gen_store2i(TCGv_env tcg_env,TCGv vaddr,int32_t src,uint32_t slot)433*ad75a51eSRichard Henderson void gen_store2i(TCGv_env tcg_env, TCGv vaddr, int32_t src, uint32_t slot)
43446ef47e2STaylor Simpson {
43523803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
436*ad75a51eSRichard Henderson     gen_store2(tcg_env, vaddr, tmp, slot);
43746ef47e2STaylor Simpson }
43846ef47e2STaylor Simpson 
gen_store4(TCGv_env tcg_env,TCGv vaddr,TCGv src,uint32_t slot)439*ad75a51eSRichard Henderson void gen_store4(TCGv_env tcg_env, TCGv vaddr, TCGv src, uint32_t slot)
44046ef47e2STaylor Simpson {
44146ef47e2STaylor Simpson     gen_store32(vaddr, src, 4, slot);
44246ef47e2STaylor Simpson }
44346ef47e2STaylor Simpson 
gen_store4i(TCGv_env tcg_env,TCGv vaddr,int32_t src,uint32_t slot)444*ad75a51eSRichard Henderson void gen_store4i(TCGv_env tcg_env, TCGv vaddr, int32_t src, uint32_t slot)
44546ef47e2STaylor Simpson {
44623803bbeSPhilippe Mathieu-Daudé     TCGv tmp = tcg_constant_tl(src);
447*ad75a51eSRichard Henderson     gen_store4(tcg_env, vaddr, tmp, slot);
44846ef47e2STaylor Simpson }
44946ef47e2STaylor Simpson 
gen_store8(TCGv_env tcg_env,TCGv vaddr,TCGv_i64 src,uint32_t slot)450*ad75a51eSRichard Henderson void gen_store8(TCGv_env tcg_env, TCGv vaddr, TCGv_i64 src, uint32_t slot)
45146ef47e2STaylor Simpson {
45246ef47e2STaylor Simpson     tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
45346ef47e2STaylor Simpson     tcg_gen_movi_tl(hex_store_width[slot], 8);
45446ef47e2STaylor Simpson     tcg_gen_mov_i64(hex_store_val64[slot], src);
45546ef47e2STaylor Simpson }
45646ef47e2STaylor Simpson 
gen_store8i(TCGv_env tcg_env,TCGv vaddr,int64_t src,uint32_t slot)457*ad75a51eSRichard Henderson void gen_store8i(TCGv_env tcg_env, TCGv vaddr, int64_t src, uint32_t slot)
45846ef47e2STaylor Simpson {
45923803bbeSPhilippe Mathieu-Daudé     TCGv_i64 tmp = tcg_constant_i64(src);
460*ad75a51eSRichard Henderson     gen_store8(tcg_env, vaddr, tmp, slot);
46146ef47e2STaylor Simpson }
46246ef47e2STaylor Simpson 
gen_8bitsof(TCGv result,TCGv value)4637e8b3b39SPaolo Montesel TCGv gen_8bitsof(TCGv result, TCGv value)
46457d352acSTaylor Simpson {
46523803bbeSPhilippe Mathieu-Daudé     TCGv zero = tcg_constant_tl(0);
46623803bbeSPhilippe Mathieu-Daudé     TCGv ones = tcg_constant_tl(0xff);
46757d352acSTaylor Simpson     tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero);
46857d352acSTaylor Simpson 
46957d352acSTaylor Simpson     return result;
47057d352acSTaylor Simpson }
47157d352acSTaylor Simpson 
gen_write_new_pc_addr(DisasContext * ctx,TCGv addr,TCGCond cond,TCGv pred)47261c6c06eSTaylor Simpson static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
47361c6c06eSTaylor Simpson                                   TCGCond cond, TCGv pred)
47461c6c06eSTaylor Simpson {
47561c6c06eSTaylor Simpson     TCGLabel *pred_false = NULL;
47661c6c06eSTaylor Simpson     if (cond != TCG_COND_ALWAYS) {
47761c6c06eSTaylor Simpson         pred_false = gen_new_label();
47861c6c06eSTaylor Simpson         tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
47961c6c06eSTaylor Simpson     }
48061c6c06eSTaylor Simpson 
48161c6c06eSTaylor Simpson     if (ctx->pkt->pkt_has_multi_cof) {
48261c6c06eSTaylor Simpson         /* If there are multiple branches in a packet, ignore the second one */
48361c6c06eSTaylor Simpson         tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
4840fc56c43STaylor Simpson                            ctx->branch_taken, tcg_constant_tl(0),
48561c6c06eSTaylor Simpson                            hex_gpr[HEX_REG_PC], addr);
4860fc56c43STaylor Simpson         tcg_gen_movi_tl(ctx->branch_taken, 1);
48761c6c06eSTaylor Simpson     } else {
48861c6c06eSTaylor Simpson         tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
48961c6c06eSTaylor Simpson     }
49061c6c06eSTaylor Simpson 
49161c6c06eSTaylor Simpson     if (cond != TCG_COND_ALWAYS) {
49261c6c06eSTaylor Simpson         gen_set_label(pred_false);
49361c6c06eSTaylor Simpson     }
49461c6c06eSTaylor Simpson }
49561c6c06eSTaylor Simpson 
gen_write_new_pc_pcrel(DisasContext * ctx,int pc_off,TCGCond cond,TCGv pred)49661c6c06eSTaylor Simpson static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
49761c6c06eSTaylor Simpson                                    TCGCond cond, TCGv pred)
49861c6c06eSTaylor Simpson {
49961c6c06eSTaylor Simpson     target_ulong dest = ctx->pkt->pc + pc_off;
5001b9a7f2aSTaylor Simpson     if (ctx->pkt->pkt_has_multi_cof) {
50161c6c06eSTaylor Simpson         gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
5021b9a7f2aSTaylor Simpson     } else {
5031b9a7f2aSTaylor Simpson         /* Defer this jump to the end of the TB */
5041b9a7f2aSTaylor Simpson         ctx->branch_cond = TCG_COND_ALWAYS;
5051b9a7f2aSTaylor Simpson         if (pred != NULL) {
5061b9a7f2aSTaylor Simpson             ctx->branch_cond = cond;
5070fc56c43STaylor Simpson             tcg_gen_mov_tl(ctx->branch_taken, pred);
5081b9a7f2aSTaylor Simpson         }
5091b9a7f2aSTaylor Simpson         ctx->branch_dest = dest;
5101b9a7f2aSTaylor Simpson     }
51161c6c06eSTaylor Simpson }
51261c6c06eSTaylor Simpson 
gen_set_usr_field(DisasContext * ctx,int field,TCGv val)513148ef7fdSTaylor Simpson void gen_set_usr_field(DisasContext *ctx, int field, TCGv val)
514564b2040STaylor Simpson {
515148ef7fdSTaylor Simpson     TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
516148ef7fdSTaylor Simpson     tcg_gen_deposit_tl(usr, usr, val,
517564b2040STaylor Simpson                        reg_field_info[field].offset,
518564b2040STaylor Simpson                        reg_field_info[field].width);
519564b2040STaylor Simpson }
520564b2040STaylor Simpson 
gen_set_usr_fieldi(DisasContext * ctx,int field,int x)521148ef7fdSTaylor Simpson void gen_set_usr_fieldi(DisasContext *ctx, int field, int x)
522564b2040STaylor Simpson {
523564b2040STaylor Simpson     if (reg_field_info[field].width == 1) {
524148ef7fdSTaylor Simpson         TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
525564b2040STaylor Simpson         target_ulong bit = 1 << reg_field_info[field].offset;
526564b2040STaylor Simpson         if ((x & 1) == 1) {
527148ef7fdSTaylor Simpson             tcg_gen_ori_tl(usr, usr, bit);
528564b2040STaylor Simpson         } else {
529148ef7fdSTaylor Simpson             tcg_gen_andi_tl(usr, usr, ~bit);
530564b2040STaylor Simpson         }
531564b2040STaylor Simpson     } else {
532564b2040STaylor Simpson         TCGv val = tcg_constant_tl(x);
533148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, field, val);
534564b2040STaylor Simpson     }
535564b2040STaylor Simpson }
536564b2040STaylor Simpson 
gen_compare(TCGCond cond,TCGv res,TCGv arg1,TCGv arg2)53711b577ffSTaylor Simpson static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
53811b577ffSTaylor Simpson {
53911b577ffSTaylor Simpson     TCGv one = tcg_constant_tl(0xff);
54011b577ffSTaylor Simpson     TCGv zero = tcg_constant_tl(0);
54111b577ffSTaylor Simpson 
54211b577ffSTaylor Simpson     tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
54311b577ffSTaylor Simpson }
54411b577ffSTaylor Simpson 
54517fda3c2STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
gen_loop0r(DisasContext * ctx,TCGv RsV,int riV)54617fda3c2STaylor Simpson static inline void gen_loop0r(DisasContext *ctx, TCGv RsV, int riV)
54717fda3c2STaylor Simpson {
54817fda3c2STaylor Simpson     fIMMEXT(riV);
54917fda3c2STaylor Simpson     fPCALIGN(riV);
55017fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_LC0, RsV);
55117fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV));
55217fda3c2STaylor Simpson     gen_set_usr_fieldi(ctx, USR_LPCFG, 0);
55317fda3c2STaylor Simpson }
55417fda3c2STaylor Simpson 
gen_loop0i(DisasContext * ctx,int count,int riV)55517fda3c2STaylor Simpson static void gen_loop0i(DisasContext *ctx, int count, int riV)
55617fda3c2STaylor Simpson {
55717fda3c2STaylor Simpson     gen_loop0r(ctx, tcg_constant_tl(count), riV);
55817fda3c2STaylor Simpson }
55917fda3c2STaylor Simpson 
gen_loop1r(DisasContext * ctx,TCGv RsV,int riV)56017fda3c2STaylor Simpson static inline void gen_loop1r(DisasContext *ctx, TCGv RsV, int riV)
56117fda3c2STaylor Simpson {
56217fda3c2STaylor Simpson     fIMMEXT(riV);
56317fda3c2STaylor Simpson     fPCALIGN(riV);
56417fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_LC1, RsV);
56517fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SA1, tcg_constant_tl(ctx->pkt->pc + riV));
56617fda3c2STaylor Simpson }
56717fda3c2STaylor Simpson 
gen_loop1i(DisasContext * ctx,int count,int riV)56817fda3c2STaylor Simpson static void gen_loop1i(DisasContext *ctx, int count, int riV)
56917fda3c2STaylor Simpson {
57017fda3c2STaylor Simpson     gen_loop1r(ctx, tcg_constant_tl(count), riV);
57117fda3c2STaylor Simpson }
57217fda3c2STaylor Simpson 
gen_ploopNsr(DisasContext * ctx,int N,TCGv RsV,int riV)57317fda3c2STaylor Simpson static void gen_ploopNsr(DisasContext *ctx, int N, TCGv RsV, int riV)
57417fda3c2STaylor Simpson {
57517fda3c2STaylor Simpson     fIMMEXT(riV);
57617fda3c2STaylor Simpson     fPCALIGN(riV);
57717fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_LC0, RsV);
57817fda3c2STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV));
57917fda3c2STaylor Simpson     gen_set_usr_fieldi(ctx, USR_LPCFG, N);
58017fda3c2STaylor Simpson     gen_log_pred_write(ctx, 3, tcg_constant_tl(0));
58117fda3c2STaylor Simpson }
58217fda3c2STaylor Simpson 
gen_ploopNsi(DisasContext * ctx,int N,int count,int riV)58317fda3c2STaylor Simpson static void gen_ploopNsi(DisasContext *ctx, int N, int count, int riV)
58417fda3c2STaylor Simpson {
58517fda3c2STaylor Simpson     gen_ploopNsr(ctx, N, tcg_constant_tl(count), riV);
58617fda3c2STaylor Simpson }
587d24f0b2bSTaylor Simpson 
gen_comparei(TCGCond cond,TCGv res,TCGv arg1,int arg2)588d24f0b2bSTaylor Simpson static inline void gen_comparei(TCGCond cond, TCGv res, TCGv arg1, int arg2)
589d24f0b2bSTaylor Simpson {
590d24f0b2bSTaylor Simpson     gen_compare(cond, res, arg1, tcg_constant_tl(arg2));
591d24f0b2bSTaylor Simpson }
59217fda3c2STaylor Simpson #endif
59317fda3c2STaylor Simpson 
gen_cond_jumpr(DisasContext * ctx,TCGv dst_pc,TCGCond cond,TCGv pred)59497b16fafSTaylor Simpson static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
59597b16fafSTaylor Simpson                            TCGCond cond, TCGv pred)
59697b16fafSTaylor Simpson {
59797b16fafSTaylor Simpson     gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
59897b16fafSTaylor Simpson }
59997b16fafSTaylor Simpson 
gen_cond_jumpr31(DisasContext * ctx,TCGCond cond,TCGv pred)6005ef5fdbaSTaylor Simpson static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred)
6015ef5fdbaSTaylor Simpson {
6025ef5fdbaSTaylor Simpson     TCGv LSB = tcg_temp_new();
6035ef5fdbaSTaylor Simpson     tcg_gen_andi_tl(LSB, pred, 1);
6045ef5fdbaSTaylor Simpson     gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB);
6055ef5fdbaSTaylor Simpson }
6065ef5fdbaSTaylor Simpson 
gen_cond_jump(DisasContext * ctx,TCGCond cond,TCGv pred,int pc_off)60711b577ffSTaylor Simpson static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
60811b577ffSTaylor Simpson                           int pc_off)
60911b577ffSTaylor Simpson {
61011b577ffSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
61111b577ffSTaylor Simpson }
61211b577ffSTaylor Simpson 
gen_cmpnd_cmp_jmp(DisasContext * ctx,int pnum,TCGCond cond1,TCGv arg1,TCGv arg2,TCGCond cond2,int pc_off)61311b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp(DisasContext *ctx,
61411b577ffSTaylor Simpson                               int pnum, TCGCond cond1, TCGv arg1, TCGv arg2,
61511b577ffSTaylor Simpson                               TCGCond cond2, int pc_off)
61611b577ffSTaylor Simpson {
61711b577ffSTaylor Simpson     if (ctx->insn->part1) {
61811b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
61911b577ffSTaylor Simpson         gen_compare(cond1, pred, arg1, arg2);
62011b577ffSTaylor Simpson         gen_log_pred_write(ctx, pnum, pred);
62111b577ffSTaylor Simpson     } else {
62211b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
623e22edc7cSTaylor Simpson         tcg_gen_mov_tl(pred, ctx->new_pred_value[pnum]);
62411b577ffSTaylor Simpson         gen_cond_jump(ctx, cond2, pred, pc_off);
62511b577ffSTaylor Simpson     }
62611b577ffSTaylor Simpson }
62711b577ffSTaylor Simpson 
gen_cmpnd_cmp_jmp_t(DisasContext * ctx,int pnum,TCGCond cond,TCGv arg1,TCGv arg2,int pc_off)62811b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
62911b577ffSTaylor Simpson                                 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
63011b577ffSTaylor Simpson                                 int pc_off)
63111b577ffSTaylor Simpson {
63211b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
63311b577ffSTaylor Simpson }
63411b577ffSTaylor Simpson 
gen_cmpnd_cmp_jmp_f(DisasContext * ctx,int pnum,TCGCond cond,TCGv arg1,TCGv arg2,int pc_off)63511b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
63611b577ffSTaylor Simpson                                 int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
63711b577ffSTaylor Simpson                                 int pc_off)
63811b577ffSTaylor Simpson {
63911b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
64011b577ffSTaylor Simpson }
64111b577ffSTaylor Simpson 
gen_cmpnd_cmpi_jmp_t(DisasContext * ctx,int pnum,TCGCond cond,TCGv arg1,int arg2,int pc_off)64211b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
64311b577ffSTaylor Simpson                                  int pnum, TCGCond cond, TCGv arg1, int arg2,
64411b577ffSTaylor Simpson                                  int pc_off)
64511b577ffSTaylor Simpson {
64611b577ffSTaylor Simpson     TCGv tmp = tcg_constant_tl(arg2);
64711b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
64811b577ffSTaylor Simpson }
64911b577ffSTaylor Simpson 
gen_cmpnd_cmpi_jmp_f(DisasContext * ctx,int pnum,TCGCond cond,TCGv arg1,int arg2,int pc_off)65011b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
65111b577ffSTaylor Simpson                                  int pnum, TCGCond cond, TCGv arg1, int arg2,
65211b577ffSTaylor Simpson                                  int pc_off)
65311b577ffSTaylor Simpson {
65411b577ffSTaylor Simpson     TCGv tmp = tcg_constant_tl(arg2);
65511b577ffSTaylor Simpson     gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
65611b577ffSTaylor Simpson }
65711b577ffSTaylor Simpson 
gen_cmpnd_cmp_n1_jmp_t(DisasContext * ctx,int pnum,TCGCond cond,TCGv arg,int pc_off)65811b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
65911b577ffSTaylor Simpson                                    TCGv arg, int pc_off)
66011b577ffSTaylor Simpson {
66111b577ffSTaylor Simpson     gen_cmpnd_cmpi_jmp_t(ctx, pnum, cond, arg, -1, pc_off);
66211b577ffSTaylor Simpson }
66311b577ffSTaylor Simpson 
gen_cmpnd_cmp_n1_jmp_f(DisasContext * ctx,int pnum,TCGCond cond,TCGv arg,int pc_off)66411b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_f(DisasContext *ctx, int pnum, TCGCond cond,
66511b577ffSTaylor Simpson                                    TCGv arg, int pc_off)
66611b577ffSTaylor Simpson {
66711b577ffSTaylor Simpson     gen_cmpnd_cmpi_jmp_f(ctx, pnum, cond, arg, -1, pc_off);
66811b577ffSTaylor Simpson }
66911b577ffSTaylor Simpson 
gen_cmpnd_tstbit0_jmp(DisasContext * ctx,int pnum,TCGv arg,TCGCond cond,int pc_off)67011b577ffSTaylor Simpson static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
67111b577ffSTaylor Simpson                                   int pnum, TCGv arg, TCGCond cond, int pc_off)
67211b577ffSTaylor Simpson {
67311b577ffSTaylor Simpson     if (ctx->insn->part1) {
67411b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
67511b577ffSTaylor Simpson         tcg_gen_andi_tl(pred, arg, 1);
67611b577ffSTaylor Simpson         gen_8bitsof(pred, pred);
67711b577ffSTaylor Simpson         gen_log_pred_write(ctx, pnum, pred);
67811b577ffSTaylor Simpson     } else {
67911b577ffSTaylor Simpson         TCGv pred = tcg_temp_new();
680e22edc7cSTaylor Simpson         tcg_gen_mov_tl(pred, ctx->new_pred_value[pnum]);
68111b577ffSTaylor Simpson         gen_cond_jump(ctx, cond, pred, pc_off);
68211b577ffSTaylor Simpson     }
68311b577ffSTaylor Simpson }
68411b577ffSTaylor Simpson 
gen_testbit0_jumpnv(DisasContext * ctx,TCGv arg,TCGCond cond,int pc_off)68597b16fafSTaylor Simpson static void gen_testbit0_jumpnv(DisasContext *ctx,
68697b16fafSTaylor Simpson                                 TCGv arg, TCGCond cond, int pc_off)
68797b16fafSTaylor Simpson {
68897b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
68997b16fafSTaylor Simpson     tcg_gen_andi_tl(pred, arg, 1);
69097b16fafSTaylor Simpson     gen_cond_jump(ctx, cond, pred, pc_off);
69197b16fafSTaylor Simpson }
69297b16fafSTaylor Simpson 
gen_jump(DisasContext * ctx,int pc_off)69397b16fafSTaylor Simpson static void gen_jump(DisasContext *ctx, int pc_off)
69497b16fafSTaylor Simpson {
69597b16fafSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
69697b16fafSTaylor Simpson }
69797b16fafSTaylor Simpson 
gen_jumpr(DisasContext * ctx,TCGv new_pc)69897b16fafSTaylor Simpson static void gen_jumpr(DisasContext *ctx, TCGv new_pc)
69997b16fafSTaylor Simpson {
70097b16fafSTaylor Simpson     gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
70197b16fafSTaylor Simpson }
70297b16fafSTaylor Simpson 
gen_call(DisasContext * ctx,int pc_off)70361c6c06eSTaylor Simpson static void gen_call(DisasContext *ctx, int pc_off)
70461c6c06eSTaylor Simpson {
705e28b77a6STaylor Simpson     TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
706e28b77a6STaylor Simpson     tcg_gen_movi_tl(lr, ctx->next_PC);
70761c6c06eSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
70861c6c06eSTaylor Simpson }
70961c6c06eSTaylor Simpson 
gen_callr(DisasContext * ctx,TCGv new_pc)710242af2c0STaylor Simpson static void gen_callr(DisasContext *ctx, TCGv new_pc)
711242af2c0STaylor Simpson {
712e28b77a6STaylor Simpson     TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
713e28b77a6STaylor Simpson     tcg_gen_movi_tl(lr, ctx->next_PC);
714242af2c0STaylor Simpson     gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
715242af2c0STaylor Simpson }
716242af2c0STaylor Simpson 
gen_cond_call(DisasContext * ctx,TCGv pred,TCGCond cond,int pc_off)71761c6c06eSTaylor Simpson static void gen_cond_call(DisasContext *ctx, TCGv pred,
71861c6c06eSTaylor Simpson                           TCGCond cond, int pc_off)
71961c6c06eSTaylor Simpson {
720e28b77a6STaylor Simpson     TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
7217a819de8SRichard Henderson     TCGv lsb = tcg_temp_new();
72261c6c06eSTaylor Simpson     TCGLabel *skip = gen_new_label();
72361c6c06eSTaylor Simpson     tcg_gen_andi_tl(lsb, pred, 1);
72461c6c06eSTaylor Simpson     gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
72561c6c06eSTaylor Simpson     tcg_gen_brcondi_tl(cond, lsb, 0, skip);
726e28b77a6STaylor Simpson     tcg_gen_movi_tl(lr, ctx->next_PC);
72761c6c06eSTaylor Simpson     gen_set_label(skip);
72861c6c06eSTaylor Simpson }
72961c6c06eSTaylor Simpson 
gen_cond_callr(DisasContext * ctx,TCGCond cond,TCGv pred,TCGv new_pc)730242af2c0STaylor Simpson static void gen_cond_callr(DisasContext *ctx,
731242af2c0STaylor Simpson                            TCGCond cond, TCGv pred, TCGv new_pc)
732242af2c0STaylor Simpson {
733242af2c0STaylor Simpson     TCGv lsb = tcg_temp_new();
734242af2c0STaylor Simpson     TCGLabel *skip = gen_new_label();
735242af2c0STaylor Simpson     tcg_gen_andi_tl(lsb, pred, 1);
736242af2c0STaylor Simpson     tcg_gen_brcondi_tl(cond, lsb, 0, skip);
737242af2c0STaylor Simpson     gen_callr(ctx, new_pc);
738242af2c0STaylor Simpson     gen_set_label(skip);
739242af2c0STaylor Simpson }
740242af2c0STaylor Simpson 
741085b6700STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
742085b6700STaylor Simpson /* frame = ((LR << 32) | FP) ^ (FRAMEKEY << 32)) */
gen_frame_scramble(void)743085b6700STaylor Simpson static TCGv_i64 gen_frame_scramble(void)
744085b6700STaylor Simpson {
745085b6700STaylor Simpson     TCGv_i64 frame = tcg_temp_new_i64();
746085b6700STaylor Simpson     TCGv tmp = tcg_temp_new();
747085b6700STaylor Simpson     tcg_gen_xor_tl(tmp, hex_gpr[HEX_REG_LR], hex_gpr[HEX_REG_FRAMEKEY]);
748085b6700STaylor Simpson     tcg_gen_concat_i32_i64(frame, hex_gpr[HEX_REG_FP], tmp);
749085b6700STaylor Simpson     return frame;
750085b6700STaylor Simpson }
751085b6700STaylor Simpson #endif
752085b6700STaylor Simpson 
753dae386b8STaylor Simpson /* frame ^= (int64_t)FRAMEKEY << 32 */
gen_frame_unscramble(TCGv_i64 frame)754dae386b8STaylor Simpson static void gen_frame_unscramble(TCGv_i64 frame)
755dae386b8STaylor Simpson {
756dae386b8STaylor Simpson     TCGv_i64 framekey = tcg_temp_new_i64();
757dae386b8STaylor Simpson     tcg_gen_extu_i32_i64(framekey, hex_gpr[HEX_REG_FRAMEKEY]);
758dae386b8STaylor Simpson     tcg_gen_shli_i64(framekey, framekey, 32);
759dae386b8STaylor Simpson     tcg_gen_xor_i64(frame, frame, framekey);
760dae386b8STaylor Simpson }
761dae386b8STaylor Simpson 
gen_load_frame(DisasContext * ctx,TCGv_i64 frame,TCGv EA)762dae386b8STaylor Simpson static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
763dae386b8STaylor Simpson {
764dae386b8STaylor Simpson     Insn *insn = ctx->insn;  /* Needed for CHECK_NOSHUF */
765dae386b8STaylor Simpson     CHECK_NOSHUF(EA, 8);
76653b26d25SRichard Henderson     tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ);
767dae386b8STaylor Simpson }
768dae386b8STaylor Simpson 
769085b6700STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER
770085b6700STaylor Simpson /* Stack overflow check */
gen_framecheck(TCGv EA,int framesize)771085b6700STaylor Simpson static void gen_framecheck(TCGv EA, int framesize)
772085b6700STaylor Simpson {
773085b6700STaylor Simpson     /* Not modelled in linux-user mode */
774085b6700STaylor Simpson     /* Placeholder for system mode */
775085b6700STaylor Simpson #ifndef CONFIG_USER_ONLY
776085b6700STaylor Simpson     g_assert_not_reached();
777085b6700STaylor Simpson #endif
778085b6700STaylor Simpson }
779085b6700STaylor Simpson 
gen_allocframe(DisasContext * ctx,TCGv r29,int framesize)780085b6700STaylor Simpson static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize)
781085b6700STaylor Simpson {
782085b6700STaylor Simpson     TCGv r30 = tcg_temp_new();
783085b6700STaylor Simpson     TCGv_i64 frame;
784085b6700STaylor Simpson     tcg_gen_addi_tl(r30, r29, -8);
785085b6700STaylor Simpson     frame = gen_frame_scramble();
786*ad75a51eSRichard Henderson     gen_store8(tcg_env, r30, frame, ctx->insn->slot);
787085b6700STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_FP, r30);
788085b6700STaylor Simpson     gen_framecheck(r30, framesize);
789085b6700STaylor Simpson     tcg_gen_subi_tl(r29, r30, framesize);
790085b6700STaylor Simpson }
791085b6700STaylor Simpson 
gen_deallocframe(DisasContext * ctx,TCGv_i64 r31_30,TCGv r30)792085b6700STaylor Simpson static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30)
793085b6700STaylor Simpson {
794085b6700STaylor Simpson     TCGv r29 = tcg_temp_new();
795085b6700STaylor Simpson     TCGv_i64 frame = tcg_temp_new_i64();
796085b6700STaylor Simpson     gen_load_frame(ctx, frame, r30);
797085b6700STaylor Simpson     gen_frame_unscramble(frame);
798085b6700STaylor Simpson     tcg_gen_mov_i64(r31_30, frame);
799085b6700STaylor Simpson     tcg_gen_addi_tl(r29, r30, 8);
800085b6700STaylor Simpson     gen_log_reg_write(ctx, HEX_REG_SP, r29);
801085b6700STaylor Simpson }
802085b6700STaylor Simpson #endif
803085b6700STaylor Simpson 
gen_return(DisasContext * ctx,TCGv_i64 dst,TCGv src)804e28b77a6STaylor Simpson static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
805dae386b8STaylor Simpson {
806dae386b8STaylor Simpson     /*
807dae386b8STaylor Simpson      * frame = *src
808dae386b8STaylor Simpson      * dst = frame_unscramble(frame)
809dae386b8STaylor Simpson      * SP = src + 8
810dae386b8STaylor Simpson      * PC = dst.w[1]
811dae386b8STaylor Simpson      */
812dae386b8STaylor Simpson     TCGv_i64 frame = tcg_temp_new_i64();
813dae386b8STaylor Simpson     TCGv r31 = tcg_temp_new();
814e28b77a6STaylor Simpson     TCGv r29 = get_result_gpr(ctx, HEX_REG_SP);
815dae386b8STaylor Simpson 
816dae386b8STaylor Simpson     gen_load_frame(ctx, frame, src);
817dae386b8STaylor Simpson     gen_frame_unscramble(frame);
818dae386b8STaylor Simpson     tcg_gen_mov_i64(dst, frame);
819dae386b8STaylor Simpson     tcg_gen_addi_tl(r29, src, 8);
820dae386b8STaylor Simpson     tcg_gen_extrh_i64_i32(r31, dst);
821dae386b8STaylor Simpson     gen_jumpr(ctx, r31);
822dae386b8STaylor Simpson }
823dae386b8STaylor Simpson 
824dae386b8STaylor Simpson /* if (pred) dst = dealloc_return(src):raw */
gen_cond_return(DisasContext * ctx,TCGv_i64 dst,TCGv src,TCGv pred,TCGCond cond)825dae386b8STaylor Simpson static void gen_cond_return(DisasContext *ctx, TCGv_i64 dst, TCGv src,
826dae386b8STaylor Simpson                             TCGv pred, TCGCond cond)
827dae386b8STaylor Simpson {
828dae386b8STaylor Simpson     TCGv LSB = tcg_temp_new();
829dae386b8STaylor Simpson     TCGLabel *skip = gen_new_label();
830dae386b8STaylor Simpson     tcg_gen_andi_tl(LSB, pred, 1);
831dae386b8STaylor Simpson 
832dae386b8STaylor Simpson     tcg_gen_brcondi_tl(cond, LSB, 0, skip);
833e28b77a6STaylor Simpson     gen_return(ctx, dst, src);
834dae386b8STaylor Simpson     gen_set_label(skip);
835dae386b8STaylor Simpson }
836dae386b8STaylor Simpson 
837dae386b8STaylor Simpson /* sub-instruction version (no RddV, so handle it manually) */
gen_cond_return_subinsn(DisasContext * ctx,TCGCond cond,TCGv pred)838dae386b8STaylor Simpson static void gen_cond_return_subinsn(DisasContext *ctx, TCGCond cond, TCGv pred)
839dae386b8STaylor Simpson {
840e28b77a6STaylor Simpson     TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP);
841dae386b8STaylor Simpson     gen_cond_return(ctx, RddV, hex_gpr[HEX_REG_FP], pred, cond);
84207540a28STaylor Simpson     gen_log_reg_write_pair(ctx, HEX_REG_FP, RddV);
843dae386b8STaylor Simpson }
844dae386b8STaylor Simpson 
gen_endloop0(DisasContext * ctx)845564b2040STaylor Simpson static void gen_endloop0(DisasContext *ctx)
846564b2040STaylor Simpson {
8477a819de8SRichard Henderson     TCGv lpcfg = tcg_temp_new();
848564b2040STaylor Simpson 
849564b2040STaylor Simpson     GET_USR_FIELD(USR_LPCFG, lpcfg);
850564b2040STaylor Simpson 
851564b2040STaylor Simpson     /*
852564b2040STaylor Simpson      *    if (lpcfg == 1) {
85325e1d87dSTaylor Simpson      *        p3 = 0xff;
854564b2040STaylor Simpson      *    }
855564b2040STaylor Simpson      */
856564b2040STaylor Simpson     TCGLabel *label1 = gen_new_label();
857564b2040STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
858564b2040STaylor Simpson     {
85925e1d87dSTaylor Simpson         gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff));
860564b2040STaylor Simpson     }
861564b2040STaylor Simpson     gen_set_label(label1);
862564b2040STaylor Simpson 
863564b2040STaylor Simpson     /*
864564b2040STaylor Simpson      *    if (lpcfg) {
865564b2040STaylor Simpson      *        SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
866564b2040STaylor Simpson      *    }
867564b2040STaylor Simpson      */
868564b2040STaylor Simpson     TCGLabel *label2 = gen_new_label();
869564b2040STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
870564b2040STaylor Simpson     {
871564b2040STaylor Simpson         tcg_gen_subi_tl(lpcfg, lpcfg, 1);
872148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, USR_LPCFG, lpcfg);
873564b2040STaylor Simpson     }
874564b2040STaylor Simpson     gen_set_label(label2);
875564b2040STaylor Simpson 
876564b2040STaylor Simpson     /*
877564b2040STaylor Simpson      * If we're in a tight loop, we'll do this at the end of the TB to take
878564b2040STaylor Simpson      * advantage of direct block chaining.
879564b2040STaylor Simpson      */
880564b2040STaylor Simpson     if (!ctx->is_tight_loop) {
881564b2040STaylor Simpson         /*
8822babbd93SMatheus Tavares Bernardino          *    if (LC0 > 1) {
8832babbd93SMatheus Tavares Bernardino          *        PC = SA0;
8842babbd93SMatheus Tavares Bernardino          *        LC0--;
885564b2040STaylor Simpson          *    }
886564b2040STaylor Simpson          */
887564b2040STaylor Simpson         TCGLabel *label3 = gen_new_label();
888564b2040STaylor Simpson         tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
889564b2040STaylor Simpson         {
890e28b77a6STaylor Simpson             TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0);
891564b2040STaylor Simpson             gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
892e28b77a6STaylor Simpson             tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1);
893564b2040STaylor Simpson         }
894564b2040STaylor Simpson         gen_set_label(label3);
895564b2040STaylor Simpson     }
896564b2040STaylor Simpson }
897564b2040STaylor Simpson 
gen_endloop1(DisasContext * ctx)898b8552a78STaylor Simpson static void gen_endloop1(DisasContext *ctx)
899b8552a78STaylor Simpson {
900b8552a78STaylor Simpson     /*
9012babbd93SMatheus Tavares Bernardino      *    if (LC1 > 1) {
9022babbd93SMatheus Tavares Bernardino      *        PC = SA1;
9032babbd93SMatheus Tavares Bernardino      *        LC1--;
904b8552a78STaylor Simpson      *    }
905b8552a78STaylor Simpson      */
906b8552a78STaylor Simpson     TCGLabel *label = gen_new_label();
907b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, label);
908b8552a78STaylor Simpson     {
909e28b77a6STaylor Simpson         TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1);
910b8552a78STaylor Simpson         gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
911e28b77a6STaylor Simpson         tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1);
912b8552a78STaylor Simpson     }
913b8552a78STaylor Simpson     gen_set_label(label);
914b8552a78STaylor Simpson }
915b8552a78STaylor Simpson 
gen_endloop01(DisasContext * ctx)916b8552a78STaylor Simpson static void gen_endloop01(DisasContext *ctx)
917b8552a78STaylor Simpson {
918b8552a78STaylor Simpson     TCGv lpcfg = tcg_temp_new();
919b8552a78STaylor Simpson     TCGLabel *label1 = gen_new_label();
920b8552a78STaylor Simpson     TCGLabel *label2 = gen_new_label();
921b8552a78STaylor Simpson     TCGLabel *label3 = gen_new_label();
922b8552a78STaylor Simpson     TCGLabel *done = gen_new_label();
923b8552a78STaylor Simpson 
924b8552a78STaylor Simpson     GET_USR_FIELD(USR_LPCFG, lpcfg);
925b8552a78STaylor Simpson 
926b8552a78STaylor Simpson     /*
927b8552a78STaylor Simpson      *    if (lpcfg == 1) {
92825e1d87dSTaylor Simpson      *        p3 = 0xff;
929b8552a78STaylor Simpson      *    }
930b8552a78STaylor Simpson      */
931b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
932b8552a78STaylor Simpson     {
93325e1d87dSTaylor Simpson         gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff));
934b8552a78STaylor Simpson     }
935b8552a78STaylor Simpson     gen_set_label(label1);
936b8552a78STaylor Simpson 
937b8552a78STaylor Simpson     /*
938b8552a78STaylor Simpson      *    if (lpcfg) {
939b8552a78STaylor Simpson      *        SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
940b8552a78STaylor Simpson      *    }
941b8552a78STaylor Simpson      */
942b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
943b8552a78STaylor Simpson     {
944b8552a78STaylor Simpson         tcg_gen_subi_tl(lpcfg, lpcfg, 1);
945148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, USR_LPCFG, lpcfg);
946b8552a78STaylor Simpson     }
947b8552a78STaylor Simpson     gen_set_label(label2);
948b8552a78STaylor Simpson 
949b8552a78STaylor Simpson     /*
9502babbd93SMatheus Tavares Bernardino      *    if (LC0 > 1) {
9512babbd93SMatheus Tavares Bernardino      *        PC = SA0;
9522babbd93SMatheus Tavares Bernardino      *        LC0--;
9532babbd93SMatheus Tavares Bernardino      *    } else if (LC1 > 1) {
9542babbd93SMatheus Tavares Bernardino      *        PC = SA1;
9552babbd93SMatheus Tavares Bernardino      *        LC1--;
956b8552a78STaylor Simpson      *    }
957b8552a78STaylor Simpson      */
958b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
959b8552a78STaylor Simpson     {
960e28b77a6STaylor Simpson         TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0);
961b8552a78STaylor Simpson         gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
962e28b77a6STaylor Simpson         tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1);
963b8552a78STaylor Simpson         tcg_gen_br(done);
964b8552a78STaylor Simpson     }
965b8552a78STaylor Simpson     gen_set_label(label3);
966b8552a78STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, done);
967b8552a78STaylor Simpson     {
968e28b77a6STaylor Simpson         TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1);
969b8552a78STaylor Simpson         gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
970e28b77a6STaylor Simpson         tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1);
971b8552a78STaylor Simpson     }
972b8552a78STaylor Simpson     gen_set_label(done);
973b8552a78STaylor Simpson }
974b8552a78STaylor Simpson 
gen_cmp_jumpnv(DisasContext * ctx,TCGCond cond,TCGv val,TCGv src,int pc_off)97597b16fafSTaylor Simpson static void gen_cmp_jumpnv(DisasContext *ctx,
97697b16fafSTaylor Simpson                            TCGCond cond, TCGv val, TCGv src, int pc_off)
97797b16fafSTaylor Simpson {
97897b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
97997b16fafSTaylor Simpson     tcg_gen_setcond_tl(cond, pred, val, src);
98097b16fafSTaylor Simpson     gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
98197b16fafSTaylor Simpson }
98297b16fafSTaylor Simpson 
gen_cmpi_jumpnv(DisasContext * ctx,TCGCond cond,TCGv val,int src,int pc_off)98397b16fafSTaylor Simpson static void gen_cmpi_jumpnv(DisasContext *ctx,
98497b16fafSTaylor Simpson                             TCGCond cond, TCGv val, int src, int pc_off)
98597b16fafSTaylor Simpson {
98697b16fafSTaylor Simpson     TCGv pred = tcg_temp_new();
98797b16fafSTaylor Simpson     tcg_gen_setcondi_tl(cond, pred, val, src);
98897b16fafSTaylor Simpson     gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
98997b16fafSTaylor Simpson }
99097b16fafSTaylor Simpson 
9918e8a85c1STaylor Simpson /* Shift left with saturation */
gen_shl_sat(DisasContext * ctx,TCGv dst,TCGv src,TCGv shift_amt)992148ef7fdSTaylor Simpson static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt)
9938e8a85c1STaylor Simpson {
99471ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dst == src */
995148ef7fdSTaylor Simpson     TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
9968e8a85c1STaylor Simpson     TCGv sh32 = tcg_temp_new();
9978e8a85c1STaylor Simpson     TCGv dst_sar = tcg_temp_new();
9988e8a85c1STaylor Simpson     TCGv ovf = tcg_temp_new();
9998e8a85c1STaylor Simpson     TCGv satval = tcg_temp_new();
10008e8a85c1STaylor Simpson     TCGv min = tcg_constant_tl(0x80000000);
10018e8a85c1STaylor Simpson     TCGv max = tcg_constant_tl(0x7fffffff);
10028e8a85c1STaylor Simpson 
10038e8a85c1STaylor Simpson     /*
10048e8a85c1STaylor Simpson      *    Possible values for shift_amt are 0 .. 64
10058e8a85c1STaylor Simpson      *    We need special handling for values above 31
10068e8a85c1STaylor Simpson      *
10078e8a85c1STaylor Simpson      *    sh32 = shift & 31;
10088e8a85c1STaylor Simpson      *    dst = sh32 == shift ? src : 0;
10098e8a85c1STaylor Simpson      *    dst <<= sh32;
10108e8a85c1STaylor Simpson      *    dst_sar = dst >> sh32;
10118e8a85c1STaylor Simpson      *    satval = src < 0 ? min : max;
10128e8a85c1STaylor Simpson      *    if (dst_asr != src) {
10138e8a85c1STaylor Simpson      *        usr.OVF |= 1;
10148e8a85c1STaylor Simpson      *        dst = satval;
10158e8a85c1STaylor Simpson      *    }
10168e8a85c1STaylor Simpson      */
10178e8a85c1STaylor Simpson 
10188e8a85c1STaylor Simpson     tcg_gen_andi_tl(sh32, shift_amt, 31);
101971ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, tmp, sh32, shift_amt,
10208e8a85c1STaylor Simpson                        src, tcg_constant_tl(0));
102171ed3697STaylor Simpson     tcg_gen_shl_tl(tmp, tmp, sh32);
102271ed3697STaylor Simpson     tcg_gen_sar_tl(dst_sar, tmp, sh32);
10238e8a85c1STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
10248e8a85c1STaylor Simpson 
10258e8a85c1STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
10268e8a85c1STaylor Simpson     tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
1027148ef7fdSTaylor Simpson     tcg_gen_or_tl(usr, usr, ovf);
10288e8a85c1STaylor Simpson 
102971ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, tmp, satval);
10308e8a85c1STaylor Simpson }
10318e8a85c1STaylor Simpson 
gen_sar(TCGv dst,TCGv src,TCGv shift_amt)10328e8a85c1STaylor Simpson static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
10338e8a85c1STaylor Simpson {
10348e8a85c1STaylor Simpson     /*
10358e8a85c1STaylor Simpson      *  Shift arithmetic right
10368e8a85c1STaylor Simpson      *  Robust when shift_amt is >31 bits
10378e8a85c1STaylor Simpson      */
10388e8a85c1STaylor Simpson     TCGv tmp = tcg_temp_new();
10398e8a85c1STaylor Simpson     tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31));
10408e8a85c1STaylor Simpson     tcg_gen_sar_tl(dst, src, tmp);
10418e8a85c1STaylor Simpson }
10428e8a85c1STaylor Simpson 
10438e8a85c1STaylor Simpson /* Bidirectional shift right with saturation */
gen_asr_r_r_sat(DisasContext * ctx,TCGv RdV,TCGv RsV,TCGv RtV)1044148ef7fdSTaylor Simpson static void gen_asr_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV)
10458e8a85c1STaylor Simpson {
10467a819de8SRichard Henderson     TCGv shift_amt = tcg_temp_new();
10478e8a85c1STaylor Simpson     TCGLabel *positive = gen_new_label();
10488e8a85c1STaylor Simpson     TCGLabel *done = gen_new_label();
10498e8a85c1STaylor Simpson 
10508e8a85c1STaylor Simpson     tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
10518e8a85c1STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
10528e8a85c1STaylor Simpson 
10538e8a85c1STaylor Simpson     /* Negative shift amount => shift left */
10548e8a85c1STaylor Simpson     tcg_gen_neg_tl(shift_amt, shift_amt);
1055148ef7fdSTaylor Simpson     gen_shl_sat(ctx, RdV, RsV, shift_amt);
10568e8a85c1STaylor Simpson     tcg_gen_br(done);
10578e8a85c1STaylor Simpson 
10588e8a85c1STaylor Simpson     gen_set_label(positive);
10598e8a85c1STaylor Simpson     /* Positive shift amount => shift right */
10608e8a85c1STaylor Simpson     gen_sar(RdV, RsV, shift_amt);
10618e8a85c1STaylor Simpson 
10628e8a85c1STaylor Simpson     gen_set_label(done);
10638e8a85c1STaylor Simpson }
10648e8a85c1STaylor Simpson 
10658e8a85c1STaylor Simpson /* Bidirectional shift left with saturation */
gen_asl_r_r_sat(DisasContext * ctx,TCGv RdV,TCGv RsV,TCGv RtV)1066148ef7fdSTaylor Simpson static void gen_asl_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV)
10678e8a85c1STaylor Simpson {
10687a819de8SRichard Henderson     TCGv shift_amt = tcg_temp_new();
10698e8a85c1STaylor Simpson     TCGLabel *positive = gen_new_label();
10708e8a85c1STaylor Simpson     TCGLabel *done = gen_new_label();
10718e8a85c1STaylor Simpson 
10728e8a85c1STaylor Simpson     tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
10738e8a85c1STaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
10748e8a85c1STaylor Simpson 
10758e8a85c1STaylor Simpson     /* Negative shift amount => shift right */
10768e8a85c1STaylor Simpson     tcg_gen_neg_tl(shift_amt, shift_amt);
10778e8a85c1STaylor Simpson     gen_sar(RdV, RsV, shift_amt);
10788e8a85c1STaylor Simpson     tcg_gen_br(done);
10798e8a85c1STaylor Simpson 
10808e8a85c1STaylor Simpson     gen_set_label(positive);
10818e8a85c1STaylor Simpson     /* Positive shift amount => shift left */
1082148ef7fdSTaylor Simpson     gen_shl_sat(ctx, RdV, RsV, shift_amt);
10838e8a85c1STaylor Simpson 
10848e8a85c1STaylor Simpson     gen_set_label(done);
10858e8a85c1STaylor Simpson }
10868e8a85c1STaylor Simpson 
gen_insert_rp(DisasContext * ctx,TCGv RxV,TCGv RsV,TCGv_i64 RttV)108700e64fdaSTaylor Simpson static void gen_insert_rp(DisasContext *ctx, TCGv RxV, TCGv RsV, TCGv_i64 RttV)
108800e64fdaSTaylor Simpson {
108900e64fdaSTaylor Simpson     /*
109000e64fdaSTaylor Simpson      * int width = fZXTN(6, 32, (fGETWORD(1, RttV)));
109100e64fdaSTaylor Simpson      * int offset = fSXTN(7, 32, (fGETWORD(0, RttV)));
109200e64fdaSTaylor Simpson      * size8u_t mask = ((fCONSTLL(1) << width) - 1);
109300e64fdaSTaylor Simpson      * if (offset < 0) {
109400e64fdaSTaylor Simpson      *     RxV = 0;
109500e64fdaSTaylor Simpson      * } else {
109600e64fdaSTaylor Simpson      *     RxV &= ~(mask << offset);
109700e64fdaSTaylor Simpson      *     RxV |= ((RsV & mask) << offset);
109800e64fdaSTaylor Simpson      * }
109900e64fdaSTaylor Simpson      */
110000e64fdaSTaylor Simpson 
110100e64fdaSTaylor Simpson     TCGv width = tcg_temp_new();
110200e64fdaSTaylor Simpson     TCGv offset = tcg_temp_new();
110300e64fdaSTaylor Simpson     TCGv_i64 mask = tcg_temp_new_i64();
110400e64fdaSTaylor Simpson     TCGv_i64 result = tcg_temp_new_i64();
110500e64fdaSTaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
110600e64fdaSTaylor Simpson     TCGv_i64 offset64 = tcg_temp_new_i64();
110700e64fdaSTaylor Simpson     TCGLabel *label = gen_new_label();
110800e64fdaSTaylor Simpson     TCGLabel *done = gen_new_label();
110900e64fdaSTaylor Simpson 
111000e64fdaSTaylor Simpson     tcg_gen_extrh_i64_i32(width, RttV);
111100e64fdaSTaylor Simpson     tcg_gen_extract_tl(width, width, 0, 6);
111200e64fdaSTaylor Simpson     tcg_gen_extrl_i64_i32(offset, RttV);
111300e64fdaSTaylor Simpson     tcg_gen_sextract_tl(offset, offset, 0, 7);
111400e64fdaSTaylor Simpson     /* Possible values for offset are -64 .. 63 */
111500e64fdaSTaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GE, offset, 0, label);
111600e64fdaSTaylor Simpson     /* For negative offsets, zero out the result */
111700e64fdaSTaylor Simpson     tcg_gen_movi_tl(RxV, 0);
111800e64fdaSTaylor Simpson     tcg_gen_br(done);
111900e64fdaSTaylor Simpson     gen_set_label(label);
112000e64fdaSTaylor Simpson     /* At this point, possible values of offset are 0 .. 63 */
112100e64fdaSTaylor Simpson     tcg_gen_ext_i32_i64(mask, width);
112200e64fdaSTaylor Simpson     tcg_gen_shl_i64(mask, tcg_constant_i64(1), mask);
112300e64fdaSTaylor Simpson     tcg_gen_subi_i64(mask, mask, 1);
112400e64fdaSTaylor Simpson     tcg_gen_extu_i32_i64(result, RxV);
112500e64fdaSTaylor Simpson     tcg_gen_ext_i32_i64(tmp, offset);
112600e64fdaSTaylor Simpson     tcg_gen_shl_i64(tmp, mask, tmp);
112700e64fdaSTaylor Simpson     tcg_gen_andc_i64(result, result, tmp);
112800e64fdaSTaylor Simpson     tcg_gen_extu_i32_i64(tmp, RsV);
112900e64fdaSTaylor Simpson     tcg_gen_and_i64(tmp, tmp, mask);
113000e64fdaSTaylor Simpson     tcg_gen_extu_i32_i64(offset64, offset);
113100e64fdaSTaylor Simpson     tcg_gen_shl_i64(tmp, tmp, offset64);
113200e64fdaSTaylor Simpson     tcg_gen_or_i64(result, result, tmp);
113300e64fdaSTaylor Simpson     tcg_gen_extrl_i64_i32(RxV, result);
113400e64fdaSTaylor Simpson     gen_set_label(done);
113500e64fdaSTaylor Simpson }
113600e64fdaSTaylor Simpson 
gen_asr_r_svw_trun(DisasContext * ctx,TCGv RdV,TCGv_i64 RssV,TCGv RtV)113700e64fdaSTaylor Simpson static void gen_asr_r_svw_trun(DisasContext *ctx, TCGv RdV,
113800e64fdaSTaylor Simpson                                TCGv_i64 RssV, TCGv RtV)
113900e64fdaSTaylor Simpson {
114000e64fdaSTaylor Simpson     /*
114100e64fdaSTaylor Simpson      * for (int i = 0; i < 2; i++) {
114200e64fdaSTaylor Simpson      *     fSETHALF(i, RdV, fGETHALF(0, ((fSXTN(7, 32, RtV) > 0) ?
114300e64fdaSTaylor Simpson      *         (fCAST4_8s(fGETWORD(i, RssV)) >> fSXTN(7, 32, RtV)) :
114400e64fdaSTaylor Simpson      *         (fCAST4_8s(fGETWORD(i, RssV)) << -fSXTN(7, 32, RtV)))));
114500e64fdaSTaylor Simpson      * }
114600e64fdaSTaylor Simpson      */
114700e64fdaSTaylor Simpson     TCGv shift_amt32 = tcg_temp_new();
114800e64fdaSTaylor Simpson     TCGv_i64 shift_amt64 = tcg_temp_new_i64();
114900e64fdaSTaylor Simpson     TCGv_i64 tmp64 = tcg_temp_new_i64();
115000e64fdaSTaylor Simpson     TCGv tmp32 = tcg_temp_new();
115100e64fdaSTaylor Simpson     TCGLabel *label = gen_new_label();
115200e64fdaSTaylor Simpson     TCGLabel *zero = gen_new_label();
115300e64fdaSTaylor Simpson     TCGLabel *done =  gen_new_label();
115400e64fdaSTaylor Simpson 
115500e64fdaSTaylor Simpson     tcg_gen_sextract_tl(shift_amt32, RtV, 0, 7);
115600e64fdaSTaylor Simpson     /* Possible values of shift_amt32 are -64 .. 63 */
115700e64fdaSTaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_LE, shift_amt32, 0, label);
115800e64fdaSTaylor Simpson     /* After branch, possible values of shift_amt32 are 1 .. 63 */
115900e64fdaSTaylor Simpson     tcg_gen_ext_i32_i64(shift_amt64, shift_amt32);
116000e64fdaSTaylor Simpson     for (int i = 0; i < 2; i++) {
116100e64fdaSTaylor Simpson         tcg_gen_sextract_i64(tmp64, RssV, i * 32, 32);
116200e64fdaSTaylor Simpson         tcg_gen_sar_i64(tmp64, tmp64, shift_amt64);
116300e64fdaSTaylor Simpson         tcg_gen_extrl_i64_i32(tmp32, tmp64);
116400e64fdaSTaylor Simpson         tcg_gen_deposit_tl(RdV, RdV, tmp32, i * 16, 16);
116500e64fdaSTaylor Simpson     }
116600e64fdaSTaylor Simpson     tcg_gen_br(done);
116700e64fdaSTaylor Simpson     gen_set_label(label);
116800e64fdaSTaylor Simpson     tcg_gen_neg_tl(shift_amt32, shift_amt32);
116900e64fdaSTaylor Simpson     /*At this point, possible values of shift_amt32 are 0 .. 64 */
117000e64fdaSTaylor Simpson     tcg_gen_brcondi_tl(TCG_COND_GT, shift_amt32, 63, zero);
117100e64fdaSTaylor Simpson     /*At this point, possible values of shift_amt32 are 0 .. 63 */
117200e64fdaSTaylor Simpson     tcg_gen_ext_i32_i64(shift_amt64, shift_amt32);
117300e64fdaSTaylor Simpson     for (int i = 0; i < 2; i++) {
117400e64fdaSTaylor Simpson         tcg_gen_sextract_i64(tmp64, RssV, i * 32, 32);
117500e64fdaSTaylor Simpson         tcg_gen_shl_i64(tmp64, tmp64, shift_amt64);
117600e64fdaSTaylor Simpson         tcg_gen_extrl_i64_i32(tmp32, tmp64);
117700e64fdaSTaylor Simpson         tcg_gen_deposit_tl(RdV, RdV, tmp32, i * 16, 16);
117800e64fdaSTaylor Simpson     }
117900e64fdaSTaylor Simpson     tcg_gen_br(done);
118000e64fdaSTaylor Simpson     gen_set_label(zero);
118100e64fdaSTaylor Simpson     /* When the shift_amt is 64, zero out the result */
118200e64fdaSTaylor Simpson     tcg_gen_movi_tl(RdV, 0);
118300e64fdaSTaylor Simpson     gen_set_label(done);
118400e64fdaSTaylor Simpson }
118500e64fdaSTaylor Simpson 
vreg_src_off(DisasContext * ctx,int num)1186887d61b2STaylor Simpson static intptr_t vreg_src_off(DisasContext *ctx, int num)
1187887d61b2STaylor Simpson {
1188887d61b2STaylor Simpson     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
1189887d61b2STaylor Simpson 
1190887d61b2STaylor Simpson     if (test_bit(num, ctx->vregs_select)) {
1191887d61b2STaylor Simpson         offset = ctx_future_vreg_off(ctx, num, 1, false);
1192887d61b2STaylor Simpson     }
1193887d61b2STaylor Simpson     if (test_bit(num, ctx->vregs_updated_tmp)) {
1194887d61b2STaylor Simpson         offset = ctx_tmp_vreg_off(ctx, num, 1, false);
1195887d61b2STaylor Simpson     }
1196887d61b2STaylor Simpson     return offset;
1197887d61b2STaylor Simpson }
1198887d61b2STaylor Simpson 
gen_log_vreg_write(DisasContext * ctx,intptr_t srcoff,int num,VRegWriteType type)1199887d61b2STaylor Simpson static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
1200c2b33d0bSTaylor Simpson                                VRegWriteType type)
1201887d61b2STaylor Simpson {
1202887d61b2STaylor Simpson     intptr_t dstoff;
1203887d61b2STaylor Simpson 
1204887d61b2STaylor Simpson     if (type != EXT_TMP) {
1205887d61b2STaylor Simpson         dstoff = ctx_future_vreg_off(ctx, num, 1, true);
1206887d61b2STaylor Simpson         tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
1207887d61b2STaylor Simpson                          sizeof(MMVector), sizeof(MMVector));
1208887d61b2STaylor Simpson     } else {
1209887d61b2STaylor Simpson         dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
1210887d61b2STaylor Simpson         tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
1211887d61b2STaylor Simpson                          sizeof(MMVector), sizeof(MMVector));
1212887d61b2STaylor Simpson     }
1213887d61b2STaylor Simpson }
1214887d61b2STaylor Simpson 
gen_log_vreg_write_pair(DisasContext * ctx,intptr_t srcoff,int num,VRegWriteType type)1215887d61b2STaylor Simpson static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
1216c2b33d0bSTaylor Simpson                                     VRegWriteType type)
1217887d61b2STaylor Simpson {
1218c2b33d0bSTaylor Simpson     gen_log_vreg_write(ctx, srcoff, num ^ 0, type);
1219887d61b2STaylor Simpson     srcoff += sizeof(MMVector);
1220c2b33d0bSTaylor Simpson     gen_log_vreg_write(ctx, srcoff, num ^ 1, type);
1221887d61b2STaylor Simpson }
1222887d61b2STaylor Simpson 
get_result_qreg(DisasContext * ctx,int qnum)1223c2b33d0bSTaylor Simpson static intptr_t get_result_qreg(DisasContext *ctx, int qnum)
1224887d61b2STaylor Simpson {
1225b8552985STaylor Simpson     if (ctx->need_commit) {
1226c2b33d0bSTaylor Simpson         return  offsetof(CPUHexagonState, future_QRegs[qnum]);
1227b8552985STaylor Simpson     } else {
1228b8552985STaylor Simpson         return  offsetof(CPUHexagonState, QRegs[qnum]);
1229b8552985STaylor Simpson     }
1230887d61b2STaylor Simpson }
1231887d61b2STaylor Simpson 
gen_vreg_load(DisasContext * ctx,intptr_t dstoff,TCGv src,bool aligned)1232887d61b2STaylor Simpson static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
1233887d61b2STaylor Simpson                           bool aligned)
1234887d61b2STaylor Simpson {
1235887d61b2STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
1236887d61b2STaylor Simpson     if (aligned) {
1237887d61b2STaylor Simpson         tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1));
1238887d61b2STaylor Simpson     }
1239887d61b2STaylor Simpson     for (int i = 0; i < sizeof(MMVector) / 8; i++) {
124053b26d25SRichard Henderson         tcg_gen_qemu_ld_i64(tmp, src, ctx->mem_idx, MO_TEUQ);
1241887d61b2STaylor Simpson         tcg_gen_addi_tl(src, src, 8);
1242*ad75a51eSRichard Henderson         tcg_gen_st_i64(tmp, tcg_env, dstoff + i * 8);
1243887d61b2STaylor Simpson     }
1244887d61b2STaylor Simpson }
1245887d61b2STaylor Simpson 
gen_vreg_store(DisasContext * ctx,TCGv EA,intptr_t srcoff,int slot,bool aligned)12461e536334STaylor Simpson static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
12471e536334STaylor Simpson                            int slot, bool aligned)
1248887d61b2STaylor Simpson {
1249887d61b2STaylor Simpson     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
1250887d61b2STaylor Simpson     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
1251887d61b2STaylor Simpson 
12521e536334STaylor Simpson     if (is_gather_store_insn(ctx)) {
1253887d61b2STaylor Simpson         TCGv sl = tcg_constant_tl(slot);
1254*ad75a51eSRichard Henderson         gen_helper_gather_store(tcg_env, EA, sl);
1255887d61b2STaylor Simpson         return;
1256887d61b2STaylor Simpson     }
1257887d61b2STaylor Simpson 
1258887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
1259887d61b2STaylor Simpson     if (aligned) {
1260887d61b2STaylor Simpson         tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
1261887d61b2STaylor Simpson                         ~((int32_t)sizeof(MMVector) - 1));
1262887d61b2STaylor Simpson     } else {
1263887d61b2STaylor Simpson         tcg_gen_mov_tl(hex_vstore_addr[slot], EA);
1264887d61b2STaylor Simpson     }
1265887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
1266887d61b2STaylor Simpson 
1267887d61b2STaylor Simpson     /* Copy the data to the vstore buffer */
1268887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
1269887d61b2STaylor Simpson     /* Set the mask to all 1's */
1270887d61b2STaylor Simpson     tcg_gen_gvec_dup_imm(MO_64, maskoff, sizeof(MMQReg), sizeof(MMQReg), ~0LL);
1271887d61b2STaylor Simpson }
1272887d61b2STaylor Simpson 
gen_vreg_masked_store(DisasContext * ctx,TCGv EA,intptr_t srcoff,intptr_t bitsoff,int slot,bool invert)1273887d61b2STaylor Simpson static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
1274887d61b2STaylor Simpson                                   intptr_t bitsoff, int slot, bool invert)
1275887d61b2STaylor Simpson {
1276887d61b2STaylor Simpson     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
1277887d61b2STaylor Simpson     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
1278887d61b2STaylor Simpson 
1279887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_pending[slot], 1);
1280887d61b2STaylor Simpson     tcg_gen_andi_tl(hex_vstore_addr[slot], EA,
1281887d61b2STaylor Simpson                     ~((int32_t)sizeof(MMVector) - 1));
1282887d61b2STaylor Simpson     tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
1283887d61b2STaylor Simpson 
1284887d61b2STaylor Simpson     /* Copy the data to the vstore buffer */
1285887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
1286887d61b2STaylor Simpson     /* Copy the mask */
1287887d61b2STaylor Simpson     tcg_gen_gvec_mov(MO_64, maskoff, bitsoff, sizeof(MMQReg), sizeof(MMQReg));
1288887d61b2STaylor Simpson     if (invert) {
1289887d61b2STaylor Simpson         tcg_gen_gvec_not(MO_64, maskoff, maskoff,
1290887d61b2STaylor Simpson                          sizeof(MMQReg), sizeof(MMQReg));
1291887d61b2STaylor Simpson     }
1292887d61b2STaylor Simpson }
1293887d61b2STaylor Simpson 
vec_to_qvec(size_t size,intptr_t dstoff,intptr_t srcoff)1294887d61b2STaylor Simpson static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
1295887d61b2STaylor Simpson {
1296887d61b2STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();
1297887d61b2STaylor Simpson     TCGv_i64 word = tcg_temp_new_i64();
1298887d61b2STaylor Simpson     TCGv_i64 bits = tcg_temp_new_i64();
1299887d61b2STaylor Simpson     TCGv_i64 mask = tcg_temp_new_i64();
1300887d61b2STaylor Simpson     TCGv_i64 zero = tcg_constant_i64(0);
1301887d61b2STaylor Simpson     TCGv_i64 ones = tcg_constant_i64(~0);
1302887d61b2STaylor Simpson 
1303887d61b2STaylor Simpson     for (int i = 0; i < sizeof(MMVector) / 8; i++) {
1304*ad75a51eSRichard Henderson         tcg_gen_ld_i64(tmp, tcg_env, srcoff + i * 8);
1305887d61b2STaylor Simpson         tcg_gen_movi_i64(mask, 0);
1306887d61b2STaylor Simpson 
1307887d61b2STaylor Simpson         for (int j = 0; j < 8; j += size) {
1308887d61b2STaylor Simpson             tcg_gen_extract_i64(word, tmp, j * 8, size * 8);
1309887d61b2STaylor Simpson             tcg_gen_movcond_i64(TCG_COND_NE, bits, word, zero, ones, zero);
1310887d61b2STaylor Simpson             tcg_gen_deposit_i64(mask, mask, bits, j, size);
1311887d61b2STaylor Simpson         }
1312887d61b2STaylor Simpson 
1313*ad75a51eSRichard Henderson         tcg_gen_st8_i64(mask, tcg_env, dstoff + i);
1314887d61b2STaylor Simpson     }
1315887d61b2STaylor Simpson }
1316887d61b2STaylor Simpson 
probe_noshuf_load(TCGv va,int s,int mi)13177e8b3b39SPaolo Montesel void probe_noshuf_load(TCGv va, int s, int mi)
131815fc6badSTaylor Simpson {
131915fc6badSTaylor Simpson     TCGv size = tcg_constant_tl(s);
132015fc6badSTaylor Simpson     TCGv mem_idx = tcg_constant_tl(mi);
1321*ad75a51eSRichard Henderson     gen_helper_probe_noshuf_load(tcg_env, va, size, mem_idx);
132215fc6badSTaylor Simpson }
132315fc6badSTaylor Simpson 
132442659e04SNiccolò Izzo /*
132542659e04SNiccolò Izzo  * Note: Since this function might branch, `val` is
132642659e04SNiccolò Izzo  * required to be a `tcg_temp_local`.
132742659e04SNiccolò Izzo  */
gen_set_usr_field_if(DisasContext * ctx,int field,TCGv val)1328148ef7fdSTaylor Simpson void gen_set_usr_field_if(DisasContext *ctx, int field, TCGv val)
132942659e04SNiccolò Izzo {
133042659e04SNiccolò Izzo     /* Sets the USR field if `val` is non-zero */
133142659e04SNiccolò Izzo     if (reg_field_info[field].width == 1) {
1332148ef7fdSTaylor Simpson         TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
133342659e04SNiccolò Izzo         TCGv tmp = tcg_temp_new();
133442659e04SNiccolò Izzo         tcg_gen_extract_tl(tmp, val, 0, reg_field_info[field].width);
133542659e04SNiccolò Izzo         tcg_gen_shli_tl(tmp, tmp, reg_field_info[field].offset);
1336148ef7fdSTaylor Simpson         tcg_gen_or_tl(usr, usr, tmp);
133742659e04SNiccolò Izzo     } else {
133842659e04SNiccolò Izzo         TCGLabel *skip_label = gen_new_label();
133942659e04SNiccolò Izzo         tcg_gen_brcondi_tl(TCG_COND_EQ, val, 0, skip_label);
1340148ef7fdSTaylor Simpson         gen_set_usr_field(ctx, field, val);
134142659e04SNiccolò Izzo         gen_set_label(skip_label);
134242659e04SNiccolò Izzo     }
134342659e04SNiccolò Izzo }
134442659e04SNiccolò Izzo 
gen_sat_i32(TCGv dest,TCGv source,int width)134542659e04SNiccolò Izzo void gen_sat_i32(TCGv dest, TCGv source, int width)
134642659e04SNiccolò Izzo {
134742659e04SNiccolò Izzo     TCGv max_val = tcg_constant_tl((1 << (width - 1)) - 1);
134842659e04SNiccolò Izzo     TCGv min_val = tcg_constant_tl(-(1 << (width - 1)));
134942659e04SNiccolò Izzo     tcg_gen_smin_tl(dest, source, max_val);
135042659e04SNiccolò Izzo     tcg_gen_smax_tl(dest, dest, min_val);
135142659e04SNiccolò Izzo }
135242659e04SNiccolò Izzo 
gen_sat_i32_ovfl(TCGv ovfl,TCGv dest,TCGv source,int width)135342659e04SNiccolò Izzo void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
135442659e04SNiccolò Izzo {
135571ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dest == source */
135671ed3697STaylor Simpson     gen_sat_i32(tmp, source, width);
135771ed3697STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
135871ed3697STaylor Simpson     tcg_gen_mov_tl(dest, tmp);
135942659e04SNiccolò Izzo }
136042659e04SNiccolò Izzo 
gen_satu_i32(TCGv dest,TCGv source,int width)136142659e04SNiccolò Izzo void gen_satu_i32(TCGv dest, TCGv source, int width)
136242659e04SNiccolò Izzo {
136371ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dest == source */
136442659e04SNiccolò Izzo     TCGv max_val = tcg_constant_tl((1 << width) - 1);
136542659e04SNiccolò Izzo     TCGv zero = tcg_constant_tl(0);
136671ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_GTU, tmp, source, max_val, max_val, source);
136771ed3697STaylor Simpson     tcg_gen_movcond_tl(TCG_COND_LT, tmp, source, zero, zero, tmp);
136871ed3697STaylor Simpson     tcg_gen_mov_tl(dest, tmp);
136942659e04SNiccolò Izzo }
137042659e04SNiccolò Izzo 
gen_satu_i32_ovfl(TCGv ovfl,TCGv dest,TCGv source,int width)137142659e04SNiccolò Izzo void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
137242659e04SNiccolò Izzo {
137371ed3697STaylor Simpson     TCGv tmp = tcg_temp_new();    /* In case dest == source */
137471ed3697STaylor Simpson     gen_satu_i32(tmp, source, width);
137571ed3697STaylor Simpson     tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
137671ed3697STaylor Simpson     tcg_gen_mov_tl(dest, tmp);
137742659e04SNiccolò Izzo }
137842659e04SNiccolò Izzo 
gen_sat_i64(TCGv_i64 dest,TCGv_i64 source,int width)137942659e04SNiccolò Izzo void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
138042659e04SNiccolò Izzo {
138142659e04SNiccolò Izzo     TCGv_i64 max_val = tcg_constant_i64((1LL << (width - 1)) - 1LL);
138242659e04SNiccolò Izzo     TCGv_i64 min_val = tcg_constant_i64(-(1LL << (width - 1)));
138342659e04SNiccolò Izzo     tcg_gen_smin_i64(dest, source, max_val);
138442659e04SNiccolò Izzo     tcg_gen_smax_i64(dest, dest, min_val);
138542659e04SNiccolò Izzo }
138642659e04SNiccolò Izzo 
gen_sat_i64_ovfl(TCGv ovfl,TCGv_i64 dest,TCGv_i64 source,int width)138742659e04SNiccolò Izzo void gen_sat_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
138842659e04SNiccolò Izzo {
138971ed3697STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
139042659e04SNiccolò Izzo     TCGv_i64 ovfl_64;
139171ed3697STaylor Simpson     gen_sat_i64(tmp, source, width);
139242659e04SNiccolò Izzo     ovfl_64 = tcg_temp_new_i64();
139371ed3697STaylor Simpson     tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
139471ed3697STaylor Simpson     tcg_gen_mov_i64(dest, tmp);
139542659e04SNiccolò Izzo     tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
139642659e04SNiccolò Izzo }
139742659e04SNiccolò Izzo 
gen_satu_i64(TCGv_i64 dest,TCGv_i64 source,int width)139842659e04SNiccolò Izzo void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width)
139942659e04SNiccolò Izzo {
140071ed3697STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();    /* In case dest == source */
140142659e04SNiccolò Izzo     TCGv_i64 max_val = tcg_constant_i64((1LL << width) - 1LL);
140242659e04SNiccolò Izzo     TCGv_i64 zero = tcg_constant_i64(0);
140371ed3697STaylor Simpson     tcg_gen_movcond_i64(TCG_COND_GTU, tmp, source, max_val, max_val, source);
140471ed3697STaylor Simpson     tcg_gen_movcond_i64(TCG_COND_LT, tmp, source, zero, zero, tmp);
140571ed3697STaylor Simpson     tcg_gen_mov_i64(dest, tmp);
140642659e04SNiccolò Izzo }
140742659e04SNiccolò Izzo 
gen_satu_i64_ovfl(TCGv ovfl,TCGv_i64 dest,TCGv_i64 source,int width)140842659e04SNiccolò Izzo void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
140942659e04SNiccolò Izzo {
141071ed3697STaylor Simpson     TCGv_i64 tmp = tcg_temp_new_i64();    /* In case dest == source */
141142659e04SNiccolò Izzo     TCGv_i64 ovfl_64;
141271ed3697STaylor Simpson     gen_satu_i64(tmp, source, width);
141342659e04SNiccolò Izzo     ovfl_64 = tcg_temp_new_i64();
141471ed3697STaylor Simpson     tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
141571ed3697STaylor Simpson     tcg_gen_mov_i64(dest, tmp);
141642659e04SNiccolò Izzo     tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
141742659e04SNiccolò Izzo }
141842659e04SNiccolò Izzo 
141942659e04SNiccolò Izzo /* Implements the fADDSAT64 macro in TCG */
gen_add_sat_i64(DisasContext * ctx,TCGv_i64 ret,TCGv_i64 a,TCGv_i64 b)1420148ef7fdSTaylor Simpson void gen_add_sat_i64(DisasContext *ctx, TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
142142659e04SNiccolò Izzo {
14227a819de8SRichard Henderson     TCGv_i64 sum = tcg_temp_new_i64();
142342659e04SNiccolò Izzo     TCGv_i64 xor = tcg_temp_new_i64();
142442659e04SNiccolò Izzo     TCGv_i64 cond1 = tcg_temp_new_i64();
14257a819de8SRichard Henderson     TCGv_i64 cond2 = tcg_temp_new_i64();
142642659e04SNiccolò Izzo     TCGv_i64 cond3 = tcg_temp_new_i64();
142742659e04SNiccolò Izzo     TCGv_i64 mask = tcg_constant_i64(0x8000000000000000ULL);
142842659e04SNiccolò Izzo     TCGv_i64 max_pos = tcg_constant_i64(0x7FFFFFFFFFFFFFFFLL);
142942659e04SNiccolò Izzo     TCGv_i64 max_neg = tcg_constant_i64(0x8000000000000000LL);
143042659e04SNiccolò Izzo     TCGv_i64 zero = tcg_constant_i64(0);
143142659e04SNiccolò Izzo     TCGLabel *no_ovfl_label = gen_new_label();
143242659e04SNiccolò Izzo     TCGLabel *ovfl_label = gen_new_label();
143342659e04SNiccolò Izzo     TCGLabel *ret_label = gen_new_label();
143442659e04SNiccolò Izzo 
143542659e04SNiccolò Izzo     tcg_gen_add_i64(sum, a, b);
143642659e04SNiccolò Izzo     tcg_gen_xor_i64(xor, a, b);
143742659e04SNiccolò Izzo 
143842659e04SNiccolò Izzo     /* if (xor & mask) */
143942659e04SNiccolò Izzo     tcg_gen_and_i64(cond1, xor, mask);
144042659e04SNiccolò Izzo     tcg_gen_brcondi_i64(TCG_COND_NE, cond1, 0, no_ovfl_label);
144142659e04SNiccolò Izzo 
144242659e04SNiccolò Izzo     /* else if ((a ^ sum) & mask) */
144342659e04SNiccolò Izzo     tcg_gen_xor_i64(cond2, a, sum);
144442659e04SNiccolò Izzo     tcg_gen_and_i64(cond2, cond2, mask);
144542659e04SNiccolò Izzo     tcg_gen_brcondi_i64(TCG_COND_NE, cond2, 0, ovfl_label);
144642659e04SNiccolò Izzo     /* fallthrough to no_ovfl_label branch */
144742659e04SNiccolò Izzo 
144842659e04SNiccolò Izzo     /* if branch */
144942659e04SNiccolò Izzo     gen_set_label(no_ovfl_label);
145042659e04SNiccolò Izzo     tcg_gen_mov_i64(ret, sum);
145142659e04SNiccolò Izzo     tcg_gen_br(ret_label);
145242659e04SNiccolò Izzo 
145342659e04SNiccolò Izzo     /* else if branch */
145442659e04SNiccolò Izzo     gen_set_label(ovfl_label);
145542659e04SNiccolò Izzo     tcg_gen_and_i64(cond3, sum, mask);
145642659e04SNiccolò Izzo     tcg_gen_movcond_i64(TCG_COND_NE, ret, cond3, zero, max_pos, max_neg);
1457148ef7fdSTaylor Simpson     gen_set_usr_fieldi(ctx, USR_OVF, 1);
145842659e04SNiccolò Izzo 
145942659e04SNiccolò Izzo     gen_set_label(ret_label);
146042659e04SNiccolò Izzo }
146142659e04SNiccolò Izzo 
146257acfcdeSTaylor Simpson #include "tcg_funcs_generated.c.inc"
146357acfcdeSTaylor Simpson #include "tcg_func_table_generated.c.inc"
1464