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