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 48d54c5615STaylor Simpson 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 716aa4f1d1STaylor Simpson TCGv get_result_gpr(DisasContext *ctx, int rnum) 7257acfcdeSTaylor Simpson { 73d54c5615STaylor Simpson if (ctx->need_commit) { 746aa4f1d1STaylor Simpson if (rnum == HEX_REG_USR) { 756aa4f1d1STaylor Simpson return hex_new_value_usr; 766aa4f1d1STaylor Simpson } else { 774ff56764STaylor Simpson if (ctx->new_value[rnum] == NULL) { 784ff56764STaylor Simpson ctx->new_value[rnum] = tcg_temp_new(); 794ff56764STaylor Simpson tcg_gen_movi_tl(ctx->new_value[rnum], 0); 804ff56764STaylor Simpson } 814ff56764STaylor Simpson return ctx->new_value[rnum]; 826aa4f1d1STaylor Simpson } 83d54c5615STaylor Simpson } else { 84d54c5615STaylor Simpson return hex_gpr[rnum]; 85d54c5615STaylor Simpson } 8685580a65STaylor Simpson } 87e28b77a6STaylor Simpson 88e28b77a6STaylor Simpson static TCGv_i64 get_result_gpr_pair(DisasContext *ctx, int rnum) 89e28b77a6STaylor Simpson { 90e28b77a6STaylor Simpson TCGv_i64 result = tcg_temp_new_i64(); 91d54c5615STaylor Simpson tcg_gen_concat_i32_i64(result, get_result_gpr(ctx, rnum), 92d54c5615STaylor Simpson get_result_gpr(ctx, rnum + 1)); 93e28b77a6STaylor Simpson return result; 9457acfcdeSTaylor Simpson } 9557acfcdeSTaylor Simpson 9607540a28STaylor Simpson void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val) 9757acfcdeSTaylor Simpson { 98d63aeb3bSMarco Liebel const target_ulong reg_mask = reg_immut_masks[rnum]; 99d63aeb3bSMarco Liebel 100d63aeb3bSMarco Liebel gen_masked_reg_write(val, hex_gpr[rnum], reg_mask); 101d54c5615STaylor Simpson tcg_gen_mov_tl(get_result_gpr(ctx, rnum), val); 10285580a65STaylor Simpson if (HEX_DEBUG) { 10357acfcdeSTaylor Simpson /* Do this so HELPER(debug_commit_end) will know */ 10457acfcdeSTaylor Simpson tcg_gen_movi_tl(hex_reg_written[rnum], 1); 10585580a65STaylor Simpson } 10657acfcdeSTaylor Simpson } 10757acfcdeSTaylor Simpson 10807540a28STaylor Simpson static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val) 10957acfcdeSTaylor Simpson { 110d63aeb3bSMarco Liebel TCGv val32 = tcg_temp_new(); 111d63aeb3bSMarco Liebel 11257acfcdeSTaylor Simpson /* Low word */ 113d63aeb3bSMarco Liebel tcg_gen_extrl_i64_i32(val32, val); 114d54c5615STaylor Simpson gen_log_reg_write(ctx, rnum, val32); 11557acfcdeSTaylor Simpson 11657acfcdeSTaylor Simpson /* High word */ 117d63aeb3bSMarco Liebel tcg_gen_extrh_i64_i32(val32, val); 118d54c5615STaylor Simpson gen_log_reg_write(ctx, rnum + 1, val32); 11957acfcdeSTaylor Simpson } 12057acfcdeSTaylor Simpson 121455e169dSTaylor Simpson TCGv get_result_pred(DisasContext *ctx, int pnum) 122455e169dSTaylor Simpson { 123455e169dSTaylor Simpson if (ctx->need_commit) { 124e22edc7cSTaylor Simpson if (ctx->new_pred_value[pnum] == NULL) { 125e22edc7cSTaylor Simpson ctx->new_pred_value[pnum] = tcg_temp_new(); 126e22edc7cSTaylor Simpson tcg_gen_movi_tl(ctx->new_pred_value[pnum], 0); 127e22edc7cSTaylor Simpson } 128e22edc7cSTaylor Simpson return ctx->new_pred_value[pnum]; 129455e169dSTaylor Simpson } else { 130455e169dSTaylor Simpson return hex_pred[pnum]; 131455e169dSTaylor Simpson } 132455e169dSTaylor Simpson } 133455e169dSTaylor Simpson 1347e8b3b39SPaolo Montesel void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val) 13557acfcdeSTaylor Simpson { 136455e169dSTaylor Simpson TCGv pred = get_result_pred(ctx, pnum); 13757acfcdeSTaylor Simpson TCGv base_val = tcg_temp_new(); 13857acfcdeSTaylor Simpson 13957acfcdeSTaylor Simpson tcg_gen_andi_tl(base_val, val, 0xff); 1406c677c60STaylor Simpson 1416c677c60STaylor Simpson /* 1426c677c60STaylor Simpson * Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual 1436c677c60STaylor Simpson * 1446c677c60STaylor Simpson * Multiple writes to the same preg are and'ed together 1456c677c60STaylor Simpson * If this is the first predicate write in the packet, do a 1466c677c60STaylor Simpson * straight assignment. Otherwise, do an and. 1476c677c60STaylor Simpson */ 1486c677c60STaylor Simpson if (!test_bit(pnum, ctx->pregs_written)) { 149455e169dSTaylor Simpson tcg_gen_mov_tl(pred, base_val); 1506c677c60STaylor Simpson } else { 151455e169dSTaylor Simpson tcg_gen_and_tl(pred, pred, base_val); 1526c677c60STaylor Simpson } 15325e1d87dSTaylor Simpson if (HEX_DEBUG) { 154842b206fSTaylor Simpson tcg_gen_ori_tl(ctx->pred_written, ctx->pred_written, 1 << pnum); 15525e1d87dSTaylor Simpson } 15610849c26STaylor Simpson set_bit(pnum, ctx->pregs_written); 15757acfcdeSTaylor Simpson } 15857acfcdeSTaylor Simpson 15957acfcdeSTaylor Simpson static inline void gen_read_p3_0(TCGv control_reg) 16057acfcdeSTaylor Simpson { 16157acfcdeSTaylor Simpson tcg_gen_movi_tl(control_reg, 0); 16257acfcdeSTaylor Simpson for (int i = 0; i < NUM_PREGS; i++) { 16357acfcdeSTaylor Simpson tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8); 16457acfcdeSTaylor Simpson } 16557acfcdeSTaylor Simpson } 16657acfcdeSTaylor Simpson 16757acfcdeSTaylor Simpson /* 16857acfcdeSTaylor Simpson * Certain control registers require special handling on read 16972895676SMukilan Thiyagarajan * HEX_REG_P3_0_ALIASED aliased to the predicate registers 17057acfcdeSTaylor Simpson * -> concat the 4 predicate registers together 17157acfcdeSTaylor Simpson * HEX_REG_PC actual value stored in DisasContext 17257acfcdeSTaylor Simpson * -> assign from ctx->base.pc_next 17357acfcdeSTaylor Simpson * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext 17457acfcdeSTaylor Simpson * -> add current TB changes to existing reg value 17557acfcdeSTaylor Simpson */ 17657acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num, 17757acfcdeSTaylor Simpson TCGv dest) 17857acfcdeSTaylor Simpson { 17972895676SMukilan Thiyagarajan if (reg_num == HEX_REG_P3_0_ALIASED) { 18057acfcdeSTaylor Simpson gen_read_p3_0(dest); 18157acfcdeSTaylor Simpson } else if (reg_num == HEX_REG_PC) { 18257acfcdeSTaylor Simpson tcg_gen_movi_tl(dest, ctx->base.pc_next); 18357acfcdeSTaylor Simpson } else if (reg_num == HEX_REG_QEMU_PKT_CNT) { 18457acfcdeSTaylor Simpson tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT], 18557acfcdeSTaylor Simpson ctx->num_packets); 18657acfcdeSTaylor Simpson } else if (reg_num == HEX_REG_QEMU_INSN_CNT) { 18757acfcdeSTaylor Simpson tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT], 18857acfcdeSTaylor Simpson ctx->num_insns); 189a82dd548STaylor Simpson } else if (reg_num == HEX_REG_QEMU_HVX_CNT) { 190a82dd548STaylor Simpson tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_HVX_CNT], 191a82dd548STaylor Simpson ctx->num_hvx_insns); 19257acfcdeSTaylor Simpson } else { 19357acfcdeSTaylor Simpson tcg_gen_mov_tl(dest, hex_gpr[reg_num]); 19457acfcdeSTaylor Simpson } 19557acfcdeSTaylor Simpson } 19657acfcdeSTaylor Simpson 19757acfcdeSTaylor Simpson static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num, 19857acfcdeSTaylor Simpson TCGv_i64 dest) 19957acfcdeSTaylor Simpson { 20072895676SMukilan Thiyagarajan if (reg_num == HEX_REG_P3_0_ALIASED) { 20157acfcdeSTaylor Simpson TCGv p3_0 = tcg_temp_new(); 20257acfcdeSTaylor Simpson gen_read_p3_0(p3_0); 20357acfcdeSTaylor Simpson tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]); 20457acfcdeSTaylor Simpson } else if (reg_num == HEX_REG_PC - 1) { 20523803bbeSPhilippe Mathieu-Daudé TCGv pc = tcg_constant_tl(ctx->base.pc_next); 20657acfcdeSTaylor Simpson tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc); 20757acfcdeSTaylor Simpson } else if (reg_num == HEX_REG_QEMU_PKT_CNT) { 20857acfcdeSTaylor Simpson TCGv pkt_cnt = tcg_temp_new(); 20957acfcdeSTaylor Simpson TCGv insn_cnt = tcg_temp_new(); 21057acfcdeSTaylor Simpson tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT], 21157acfcdeSTaylor Simpson ctx->num_packets); 21257acfcdeSTaylor Simpson tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT], 21357acfcdeSTaylor Simpson ctx->num_insns); 21457acfcdeSTaylor Simpson tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt); 215a82dd548STaylor Simpson } else if (reg_num == HEX_REG_QEMU_HVX_CNT) { 216a82dd548STaylor Simpson TCGv hvx_cnt = tcg_temp_new(); 217a82dd548STaylor Simpson tcg_gen_addi_tl(hvx_cnt, hex_gpr[HEX_REG_QEMU_HVX_CNT], 218a82dd548STaylor Simpson ctx->num_hvx_insns); 219a82dd548STaylor Simpson tcg_gen_concat_i32_i64(dest, hvx_cnt, hex_gpr[reg_num + 1]); 22057acfcdeSTaylor Simpson } else { 22157acfcdeSTaylor Simpson tcg_gen_concat_i32_i64(dest, 22257acfcdeSTaylor Simpson hex_gpr[reg_num], 22357acfcdeSTaylor Simpson hex_gpr[reg_num + 1]); 22457acfcdeSTaylor Simpson } 22557acfcdeSTaylor Simpson } 22657acfcdeSTaylor Simpson 227c0d86060STaylor Simpson static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg) 22857acfcdeSTaylor Simpson { 229c0d86060STaylor Simpson TCGv hex_p8 = tcg_temp_new(); 23057acfcdeSTaylor Simpson for (int i = 0; i < NUM_PREGS; i++) { 231c0d86060STaylor Simpson tcg_gen_extract_tl(hex_p8, control_reg, i * 8, 8); 232c0d86060STaylor Simpson gen_log_pred_write(ctx, i, hex_p8); 23357acfcdeSTaylor Simpson } 23457acfcdeSTaylor Simpson } 23557acfcdeSTaylor Simpson 23657acfcdeSTaylor Simpson /* 23757acfcdeSTaylor Simpson * Certain control registers require special handling on write 23872895676SMukilan Thiyagarajan * HEX_REG_P3_0_ALIASED aliased to the predicate registers 23957acfcdeSTaylor Simpson * -> break the value across 4 predicate registers 24057acfcdeSTaylor Simpson * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext 24157acfcdeSTaylor Simpson * -> clear the changes 24257acfcdeSTaylor Simpson */ 24357acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num, 24457acfcdeSTaylor Simpson TCGv val) 24557acfcdeSTaylor Simpson { 24672895676SMukilan Thiyagarajan if (reg_num == HEX_REG_P3_0_ALIASED) { 247c0d86060STaylor Simpson gen_write_p3_0(ctx, val); 24857acfcdeSTaylor Simpson } else { 24907540a28STaylor Simpson gen_log_reg_write(ctx, reg_num, val); 25057acfcdeSTaylor Simpson if (reg_num == HEX_REG_QEMU_PKT_CNT) { 25157acfcdeSTaylor Simpson ctx->num_packets = 0; 25257acfcdeSTaylor Simpson } 25357acfcdeSTaylor Simpson if (reg_num == HEX_REG_QEMU_INSN_CNT) { 25457acfcdeSTaylor Simpson ctx->num_insns = 0; 25557acfcdeSTaylor Simpson } 256a82dd548STaylor Simpson if (reg_num == HEX_REG_QEMU_HVX_CNT) { 257a82dd548STaylor Simpson ctx->num_hvx_insns = 0; 258a82dd548STaylor Simpson } 25957acfcdeSTaylor Simpson } 26057acfcdeSTaylor Simpson } 26157acfcdeSTaylor Simpson 26257acfcdeSTaylor Simpson static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num, 26357acfcdeSTaylor Simpson TCGv_i64 val) 26457acfcdeSTaylor Simpson { 26572895676SMukilan Thiyagarajan if (reg_num == HEX_REG_P3_0_ALIASED) { 266e28b77a6STaylor Simpson TCGv result = get_result_gpr(ctx, reg_num + 1); 26757acfcdeSTaylor Simpson TCGv val32 = tcg_temp_new(); 26857acfcdeSTaylor Simpson tcg_gen_extrl_i64_i32(val32, val); 269c0d86060STaylor Simpson gen_write_p3_0(ctx, val32); 27057acfcdeSTaylor Simpson tcg_gen_extrh_i64_i32(val32, val); 271e28b77a6STaylor Simpson tcg_gen_mov_tl(result, val32); 27257acfcdeSTaylor Simpson } else { 27307540a28STaylor Simpson gen_log_reg_write_pair(ctx, reg_num, val); 27457acfcdeSTaylor Simpson if (reg_num == HEX_REG_QEMU_PKT_CNT) { 27557acfcdeSTaylor Simpson ctx->num_packets = 0; 27657acfcdeSTaylor Simpson ctx->num_insns = 0; 27757acfcdeSTaylor Simpson } 278a82dd548STaylor Simpson if (reg_num == HEX_REG_QEMU_HVX_CNT) { 279a82dd548STaylor Simpson ctx->num_hvx_insns = 0; 280a82dd548STaylor Simpson } 28157acfcdeSTaylor Simpson } 28257acfcdeSTaylor Simpson } 28357acfcdeSTaylor Simpson 2847e8b3b39SPaolo Montesel TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign) 28546ef47e2STaylor Simpson { 28646ef47e2STaylor Simpson if (sign) { 28746ef47e2STaylor Simpson tcg_gen_sextract_tl(result, src, N * 8, 8); 28846ef47e2STaylor Simpson } else { 28946ef47e2STaylor Simpson tcg_gen_extract_tl(result, src, N * 8, 8); 29046ef47e2STaylor Simpson } 29146ef47e2STaylor Simpson return result; 29246ef47e2STaylor Simpson } 29346ef47e2STaylor Simpson 2947e8b3b39SPaolo Montesel TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign) 2950a65d286STaylor Simpson { 2960a65d286STaylor Simpson TCGv_i64 res64 = tcg_temp_new_i64(); 2970a65d286STaylor Simpson if (sign) { 2980a65d286STaylor Simpson tcg_gen_sextract_i64(res64, src, N * 8, 8); 2990a65d286STaylor Simpson } else { 3000a65d286STaylor Simpson tcg_gen_extract_i64(res64, src, N * 8, 8); 3010a65d286STaylor Simpson } 3020a65d286STaylor Simpson tcg_gen_extrl_i64_i32(result, res64); 3030a65d286STaylor Simpson 3040a65d286STaylor Simpson return result; 3050a65d286STaylor Simpson } 3060a65d286STaylor Simpson 3077e8b3b39SPaolo Montesel TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign) 30846ef47e2STaylor Simpson { 30946ef47e2STaylor Simpson if (sign) { 31046ef47e2STaylor Simpson tcg_gen_sextract_tl(result, src, N * 16, 16); 31146ef47e2STaylor Simpson } else { 31246ef47e2STaylor Simpson tcg_gen_extract_tl(result, src, N * 16, 16); 31346ef47e2STaylor Simpson } 31446ef47e2STaylor Simpson return result; 31546ef47e2STaylor Simpson } 31646ef47e2STaylor Simpson 3177e8b3b39SPaolo Montesel void gen_set_half(int N, TCGv result, TCGv src) 3180d0b91a8STaylor Simpson { 3190d0b91a8STaylor Simpson tcg_gen_deposit_tl(result, result, src, N * 16, 16); 3200d0b91a8STaylor Simpson } 3210d0b91a8STaylor Simpson 3227e8b3b39SPaolo Montesel void gen_set_half_i64(int N, TCGv_i64 result, TCGv src) 3230d0b91a8STaylor Simpson { 3240d0b91a8STaylor Simpson TCGv_i64 src64 = tcg_temp_new_i64(); 3250d0b91a8STaylor Simpson tcg_gen_extu_i32_i64(src64, src); 3260d0b91a8STaylor Simpson tcg_gen_deposit_i64(result, result, src64, N * 16, 16); 3270d0b91a8STaylor Simpson } 3280d0b91a8STaylor Simpson 3297e8b3b39SPaolo Montesel void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src) 3300a65d286STaylor Simpson { 3310a65d286STaylor Simpson TCGv_i64 src64 = tcg_temp_new_i64(); 3320a65d286STaylor Simpson tcg_gen_extu_i32_i64(src64, src); 3330a65d286STaylor Simpson tcg_gen_deposit_i64(result, result, src64, N * 8, 8); 3340a65d286STaylor Simpson } 3350a65d286STaylor Simpson 33657acfcdeSTaylor Simpson static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index) 33757acfcdeSTaylor Simpson { 33853b26d25SRichard Henderson tcg_gen_qemu_ld_tl(dest, vaddr, mem_index, MO_TEUL); 33957acfcdeSTaylor Simpson tcg_gen_mov_tl(hex_llsc_addr, vaddr); 34057acfcdeSTaylor Simpson tcg_gen_mov_tl(hex_llsc_val, dest); 34157acfcdeSTaylor Simpson } 34257acfcdeSTaylor Simpson 34357acfcdeSTaylor Simpson static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index) 34457acfcdeSTaylor Simpson { 34553b26d25SRichard Henderson tcg_gen_qemu_ld_i64(dest, vaddr, mem_index, MO_TEUQ); 34657acfcdeSTaylor Simpson tcg_gen_mov_tl(hex_llsc_addr, vaddr); 34757acfcdeSTaylor Simpson tcg_gen_mov_i64(hex_llsc_val_i64, dest); 34857acfcdeSTaylor Simpson } 34957acfcdeSTaylor Simpson 35088725336STaylor Simpson static inline void gen_store_conditional4(DisasContext *ctx, 35157acfcdeSTaylor Simpson TCGv pred, TCGv vaddr, TCGv src) 35257acfcdeSTaylor Simpson { 35357acfcdeSTaylor Simpson TCGLabel *fail = gen_new_label(); 35457acfcdeSTaylor Simpson TCGLabel *done = gen_new_label(); 35557acfcdeSTaylor Simpson TCGv one, zero, tmp; 35657acfcdeSTaylor Simpson 35757acfcdeSTaylor Simpson tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail); 35857acfcdeSTaylor Simpson 35923803bbeSPhilippe Mathieu-Daudé one = tcg_constant_tl(0xff); 36023803bbeSPhilippe Mathieu-Daudé zero = tcg_constant_tl(0); 36157acfcdeSTaylor Simpson tmp = tcg_temp_new(); 36257acfcdeSTaylor Simpson tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src, 36357acfcdeSTaylor Simpson ctx->mem_idx, MO_32); 36488725336STaylor Simpson tcg_gen_movcond_tl(TCG_COND_EQ, pred, tmp, hex_llsc_val, 36557acfcdeSTaylor Simpson one, zero); 36657acfcdeSTaylor Simpson tcg_gen_br(done); 36757acfcdeSTaylor Simpson 36857acfcdeSTaylor Simpson gen_set_label(fail); 36957acfcdeSTaylor Simpson tcg_gen_movi_tl(pred, 0); 37057acfcdeSTaylor Simpson 37157acfcdeSTaylor Simpson gen_set_label(done); 37257acfcdeSTaylor Simpson tcg_gen_movi_tl(hex_llsc_addr, ~0); 37357acfcdeSTaylor Simpson } 37457acfcdeSTaylor Simpson 37588725336STaylor Simpson static inline void gen_store_conditional8(DisasContext *ctx, 37657acfcdeSTaylor Simpson TCGv pred, TCGv vaddr, TCGv_i64 src) 37757acfcdeSTaylor Simpson { 37857acfcdeSTaylor Simpson TCGLabel *fail = gen_new_label(); 37957acfcdeSTaylor Simpson TCGLabel *done = gen_new_label(); 38057acfcdeSTaylor Simpson TCGv_i64 one, zero, tmp; 38157acfcdeSTaylor Simpson 38257acfcdeSTaylor Simpson tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail); 38357acfcdeSTaylor Simpson 38423803bbeSPhilippe Mathieu-Daudé one = tcg_constant_i64(0xff); 38523803bbeSPhilippe Mathieu-Daudé zero = tcg_constant_i64(0); 38657acfcdeSTaylor Simpson tmp = tcg_temp_new_i64(); 38757acfcdeSTaylor Simpson tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src, 38857acfcdeSTaylor Simpson ctx->mem_idx, MO_64); 38957acfcdeSTaylor Simpson tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64, 39057acfcdeSTaylor Simpson one, zero); 39188725336STaylor Simpson tcg_gen_extrl_i64_i32(pred, tmp); 39257acfcdeSTaylor Simpson tcg_gen_br(done); 39357acfcdeSTaylor Simpson 39457acfcdeSTaylor Simpson gen_set_label(fail); 39557acfcdeSTaylor Simpson tcg_gen_movi_tl(pred, 0); 39657acfcdeSTaylor Simpson 39757acfcdeSTaylor Simpson gen_set_label(done); 39857acfcdeSTaylor Simpson tcg_gen_movi_tl(hex_llsc_addr, ~0); 39957acfcdeSTaylor Simpson } 40057acfcdeSTaylor Simpson 401e5d0d78dSTaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER 402e5d0d78dSTaylor Simpson static TCGv gen_slotval(DisasContext *ctx) 403e5d0d78dSTaylor Simpson { 404e5d0d78dSTaylor Simpson int slotval = (ctx->pkt->pkt_has_store_s1 & 1) | (ctx->insn->slot << 1); 405e5d0d78dSTaylor Simpson return tcg_constant_tl(slotval); 406e5d0d78dSTaylor Simpson } 407e5d0d78dSTaylor Simpson #endif 408e5d0d78dSTaylor Simpson 4097e8b3b39SPaolo Montesel void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot) 41046ef47e2STaylor Simpson { 41146ef47e2STaylor Simpson tcg_gen_mov_tl(hex_store_addr[slot], vaddr); 41246ef47e2STaylor Simpson tcg_gen_movi_tl(hex_store_width[slot], width); 41346ef47e2STaylor Simpson tcg_gen_mov_tl(hex_store_val32[slot], src); 41446ef47e2STaylor Simpson } 41546ef47e2STaylor Simpson 4167e8b3b39SPaolo Montesel void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot) 41746ef47e2STaylor Simpson { 41846ef47e2STaylor Simpson gen_store32(vaddr, src, 1, slot); 41946ef47e2STaylor Simpson } 42046ef47e2STaylor Simpson 4217e8b3b39SPaolo Montesel void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot) 42246ef47e2STaylor Simpson { 42323803bbeSPhilippe Mathieu-Daudé TCGv tmp = tcg_constant_tl(src); 424661ad999STaylor Simpson gen_store1(cpu_env, vaddr, tmp, slot); 42546ef47e2STaylor Simpson } 42646ef47e2STaylor Simpson 4277e8b3b39SPaolo Montesel void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot) 42846ef47e2STaylor Simpson { 42946ef47e2STaylor Simpson gen_store32(vaddr, src, 2, slot); 43046ef47e2STaylor Simpson } 43146ef47e2STaylor Simpson 4327e8b3b39SPaolo Montesel void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot) 43346ef47e2STaylor Simpson { 43423803bbeSPhilippe Mathieu-Daudé TCGv tmp = tcg_constant_tl(src); 435661ad999STaylor Simpson gen_store2(cpu_env, vaddr, tmp, slot); 43646ef47e2STaylor Simpson } 43746ef47e2STaylor Simpson 4387e8b3b39SPaolo Montesel void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot) 43946ef47e2STaylor Simpson { 44046ef47e2STaylor Simpson gen_store32(vaddr, src, 4, slot); 44146ef47e2STaylor Simpson } 44246ef47e2STaylor Simpson 4437e8b3b39SPaolo Montesel void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot) 44446ef47e2STaylor Simpson { 44523803bbeSPhilippe Mathieu-Daudé TCGv tmp = tcg_constant_tl(src); 446661ad999STaylor Simpson gen_store4(cpu_env, vaddr, tmp, slot); 44746ef47e2STaylor Simpson } 44846ef47e2STaylor Simpson 4497e8b3b39SPaolo Montesel void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, uint32_t slot) 45046ef47e2STaylor Simpson { 45146ef47e2STaylor Simpson tcg_gen_mov_tl(hex_store_addr[slot], vaddr); 45246ef47e2STaylor Simpson tcg_gen_movi_tl(hex_store_width[slot], 8); 45346ef47e2STaylor Simpson tcg_gen_mov_i64(hex_store_val64[slot], src); 45446ef47e2STaylor Simpson } 45546ef47e2STaylor Simpson 4567e8b3b39SPaolo Montesel void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, uint32_t slot) 45746ef47e2STaylor Simpson { 45823803bbeSPhilippe Mathieu-Daudé TCGv_i64 tmp = tcg_constant_i64(src); 459661ad999STaylor Simpson gen_store8(cpu_env, vaddr, tmp, slot); 46046ef47e2STaylor Simpson } 46146ef47e2STaylor Simpson 4627e8b3b39SPaolo Montesel TCGv gen_8bitsof(TCGv result, TCGv value) 46357d352acSTaylor Simpson { 46423803bbeSPhilippe Mathieu-Daudé TCGv zero = tcg_constant_tl(0); 46523803bbeSPhilippe Mathieu-Daudé TCGv ones = tcg_constant_tl(0xff); 46657d352acSTaylor Simpson tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero); 46757d352acSTaylor Simpson 46857d352acSTaylor Simpson return result; 46957d352acSTaylor Simpson } 47057d352acSTaylor Simpson 47161c6c06eSTaylor Simpson static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr, 47261c6c06eSTaylor Simpson TCGCond cond, TCGv pred) 47361c6c06eSTaylor Simpson { 47461c6c06eSTaylor Simpson TCGLabel *pred_false = NULL; 47561c6c06eSTaylor Simpson if (cond != TCG_COND_ALWAYS) { 47661c6c06eSTaylor Simpson pred_false = gen_new_label(); 47761c6c06eSTaylor Simpson tcg_gen_brcondi_tl(cond, pred, 0, pred_false); 47861c6c06eSTaylor Simpson } 47961c6c06eSTaylor Simpson 48061c6c06eSTaylor Simpson if (ctx->pkt->pkt_has_multi_cof) { 48161c6c06eSTaylor Simpson /* If there are multiple branches in a packet, ignore the second one */ 48261c6c06eSTaylor Simpson tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC], 4830fc56c43STaylor Simpson ctx->branch_taken, tcg_constant_tl(0), 48461c6c06eSTaylor Simpson hex_gpr[HEX_REG_PC], addr); 4850fc56c43STaylor Simpson tcg_gen_movi_tl(ctx->branch_taken, 1); 48661c6c06eSTaylor Simpson } else { 48761c6c06eSTaylor Simpson tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr); 48861c6c06eSTaylor Simpson } 48961c6c06eSTaylor Simpson 49061c6c06eSTaylor Simpson if (cond != TCG_COND_ALWAYS) { 49161c6c06eSTaylor Simpson gen_set_label(pred_false); 49261c6c06eSTaylor Simpson } 49361c6c06eSTaylor Simpson } 49461c6c06eSTaylor Simpson 49561c6c06eSTaylor Simpson static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off, 49661c6c06eSTaylor Simpson TCGCond cond, TCGv pred) 49761c6c06eSTaylor Simpson { 49861c6c06eSTaylor Simpson target_ulong dest = ctx->pkt->pc + pc_off; 4991b9a7f2aSTaylor Simpson if (ctx->pkt->pkt_has_multi_cof) { 50061c6c06eSTaylor Simpson gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred); 5011b9a7f2aSTaylor Simpson } else { 5021b9a7f2aSTaylor Simpson /* Defer this jump to the end of the TB */ 5031b9a7f2aSTaylor Simpson ctx->branch_cond = TCG_COND_ALWAYS; 5041b9a7f2aSTaylor Simpson if (pred != NULL) { 5051b9a7f2aSTaylor Simpson ctx->branch_cond = cond; 5060fc56c43STaylor Simpson tcg_gen_mov_tl(ctx->branch_taken, pred); 5071b9a7f2aSTaylor Simpson } 5081b9a7f2aSTaylor Simpson ctx->branch_dest = dest; 5091b9a7f2aSTaylor Simpson } 51061c6c06eSTaylor Simpson } 51161c6c06eSTaylor Simpson 512148ef7fdSTaylor Simpson void gen_set_usr_field(DisasContext *ctx, int field, TCGv val) 513564b2040STaylor Simpson { 514148ef7fdSTaylor Simpson TCGv usr = get_result_gpr(ctx, HEX_REG_USR); 515148ef7fdSTaylor Simpson tcg_gen_deposit_tl(usr, usr, val, 516564b2040STaylor Simpson reg_field_info[field].offset, 517564b2040STaylor Simpson reg_field_info[field].width); 518564b2040STaylor Simpson } 519564b2040STaylor Simpson 520148ef7fdSTaylor Simpson void gen_set_usr_fieldi(DisasContext *ctx, int field, int x) 521564b2040STaylor Simpson { 522564b2040STaylor Simpson if (reg_field_info[field].width == 1) { 523148ef7fdSTaylor Simpson TCGv usr = get_result_gpr(ctx, HEX_REG_USR); 524564b2040STaylor Simpson target_ulong bit = 1 << reg_field_info[field].offset; 525564b2040STaylor Simpson if ((x & 1) == 1) { 526148ef7fdSTaylor Simpson tcg_gen_ori_tl(usr, usr, bit); 527564b2040STaylor Simpson } else { 528148ef7fdSTaylor Simpson tcg_gen_andi_tl(usr, usr, ~bit); 529564b2040STaylor Simpson } 530564b2040STaylor Simpson } else { 531564b2040STaylor Simpson TCGv val = tcg_constant_tl(x); 532148ef7fdSTaylor Simpson gen_set_usr_field(ctx, field, val); 533564b2040STaylor Simpson } 534564b2040STaylor Simpson } 535564b2040STaylor Simpson 53611b577ffSTaylor Simpson static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2) 53711b577ffSTaylor Simpson { 53811b577ffSTaylor Simpson TCGv one = tcg_constant_tl(0xff); 53911b577ffSTaylor Simpson TCGv zero = tcg_constant_tl(0); 54011b577ffSTaylor Simpson 54111b577ffSTaylor Simpson tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero); 54211b577ffSTaylor Simpson } 54311b577ffSTaylor Simpson 54417fda3c2STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER 54517fda3c2STaylor Simpson static inline void gen_loop0r(DisasContext *ctx, TCGv RsV, int riV) 54617fda3c2STaylor Simpson { 54717fda3c2STaylor Simpson fIMMEXT(riV); 54817fda3c2STaylor Simpson fPCALIGN(riV); 54917fda3c2STaylor Simpson gen_log_reg_write(ctx, HEX_REG_LC0, RsV); 55017fda3c2STaylor Simpson gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV)); 55117fda3c2STaylor Simpson gen_set_usr_fieldi(ctx, USR_LPCFG, 0); 55217fda3c2STaylor Simpson } 55317fda3c2STaylor Simpson 55417fda3c2STaylor Simpson static void gen_loop0i(DisasContext *ctx, int count, int riV) 55517fda3c2STaylor Simpson { 55617fda3c2STaylor Simpson gen_loop0r(ctx, tcg_constant_tl(count), riV); 55717fda3c2STaylor Simpson } 55817fda3c2STaylor Simpson 55917fda3c2STaylor Simpson static inline void gen_loop1r(DisasContext *ctx, TCGv RsV, int riV) 56017fda3c2STaylor Simpson { 56117fda3c2STaylor Simpson fIMMEXT(riV); 56217fda3c2STaylor Simpson fPCALIGN(riV); 56317fda3c2STaylor Simpson gen_log_reg_write(ctx, HEX_REG_LC1, RsV); 56417fda3c2STaylor Simpson gen_log_reg_write(ctx, HEX_REG_SA1, tcg_constant_tl(ctx->pkt->pc + riV)); 56517fda3c2STaylor Simpson } 56617fda3c2STaylor Simpson 56717fda3c2STaylor Simpson static void gen_loop1i(DisasContext *ctx, int count, int riV) 56817fda3c2STaylor Simpson { 56917fda3c2STaylor Simpson gen_loop1r(ctx, tcg_constant_tl(count), riV); 57017fda3c2STaylor Simpson } 57117fda3c2STaylor Simpson 57217fda3c2STaylor Simpson static void gen_ploopNsr(DisasContext *ctx, int N, TCGv RsV, int riV) 57317fda3c2STaylor Simpson { 57417fda3c2STaylor Simpson fIMMEXT(riV); 57517fda3c2STaylor Simpson fPCALIGN(riV); 57617fda3c2STaylor Simpson gen_log_reg_write(ctx, HEX_REG_LC0, RsV); 57717fda3c2STaylor Simpson gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV)); 57817fda3c2STaylor Simpson gen_set_usr_fieldi(ctx, USR_LPCFG, N); 57917fda3c2STaylor Simpson gen_log_pred_write(ctx, 3, tcg_constant_tl(0)); 58017fda3c2STaylor Simpson } 58117fda3c2STaylor Simpson 58217fda3c2STaylor Simpson static void gen_ploopNsi(DisasContext *ctx, int N, int count, int riV) 58317fda3c2STaylor Simpson { 58417fda3c2STaylor Simpson gen_ploopNsr(ctx, N, tcg_constant_tl(count), riV); 58517fda3c2STaylor Simpson } 586d24f0b2bSTaylor Simpson 587d24f0b2bSTaylor Simpson static inline void gen_comparei(TCGCond cond, TCGv res, TCGv arg1, int arg2) 588d24f0b2bSTaylor Simpson { 589d24f0b2bSTaylor Simpson gen_compare(cond, res, arg1, tcg_constant_tl(arg2)); 590d24f0b2bSTaylor Simpson } 59117fda3c2STaylor Simpson #endif 59217fda3c2STaylor Simpson 59397b16fafSTaylor Simpson static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc, 59497b16fafSTaylor Simpson TCGCond cond, TCGv pred) 59597b16fafSTaylor Simpson { 59697b16fafSTaylor Simpson gen_write_new_pc_addr(ctx, dst_pc, cond, pred); 59797b16fafSTaylor Simpson } 59897b16fafSTaylor Simpson 5995ef5fdbaSTaylor Simpson static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred) 6005ef5fdbaSTaylor Simpson { 6015ef5fdbaSTaylor Simpson TCGv LSB = tcg_temp_new(); 6025ef5fdbaSTaylor Simpson tcg_gen_andi_tl(LSB, pred, 1); 6035ef5fdbaSTaylor Simpson gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB); 6045ef5fdbaSTaylor Simpson } 6055ef5fdbaSTaylor Simpson 60611b577ffSTaylor Simpson static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred, 60711b577ffSTaylor Simpson int pc_off) 60811b577ffSTaylor Simpson { 60911b577ffSTaylor Simpson gen_write_new_pc_pcrel(ctx, pc_off, cond, pred); 61011b577ffSTaylor Simpson } 61111b577ffSTaylor Simpson 61211b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp(DisasContext *ctx, 61311b577ffSTaylor Simpson int pnum, TCGCond cond1, TCGv arg1, TCGv arg2, 61411b577ffSTaylor Simpson TCGCond cond2, int pc_off) 61511b577ffSTaylor Simpson { 61611b577ffSTaylor Simpson if (ctx->insn->part1) { 61711b577ffSTaylor Simpson TCGv pred = tcg_temp_new(); 61811b577ffSTaylor Simpson gen_compare(cond1, pred, arg1, arg2); 61911b577ffSTaylor Simpson gen_log_pred_write(ctx, pnum, pred); 62011b577ffSTaylor Simpson } else { 62111b577ffSTaylor Simpson TCGv pred = tcg_temp_new(); 622e22edc7cSTaylor Simpson tcg_gen_mov_tl(pred, ctx->new_pred_value[pnum]); 62311b577ffSTaylor Simpson gen_cond_jump(ctx, cond2, pred, pc_off); 62411b577ffSTaylor Simpson } 62511b577ffSTaylor Simpson } 62611b577ffSTaylor Simpson 62711b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx, 62811b577ffSTaylor Simpson int pnum, TCGCond cond, TCGv arg1, TCGv arg2, 62911b577ffSTaylor Simpson int pc_off) 63011b577ffSTaylor Simpson { 63111b577ffSTaylor Simpson gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off); 63211b577ffSTaylor Simpson } 63311b577ffSTaylor Simpson 63411b577ffSTaylor Simpson static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx, 63511b577ffSTaylor Simpson int pnum, TCGCond cond, TCGv arg1, TCGv arg2, 63611b577ffSTaylor Simpson int pc_off) 63711b577ffSTaylor Simpson { 63811b577ffSTaylor Simpson gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off); 63911b577ffSTaylor Simpson } 64011b577ffSTaylor Simpson 64111b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx, 64211b577ffSTaylor Simpson int pnum, TCGCond cond, TCGv arg1, int arg2, 64311b577ffSTaylor Simpson int pc_off) 64411b577ffSTaylor Simpson { 64511b577ffSTaylor Simpson TCGv tmp = tcg_constant_tl(arg2); 64611b577ffSTaylor Simpson gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off); 64711b577ffSTaylor Simpson } 64811b577ffSTaylor Simpson 64911b577ffSTaylor Simpson static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx, 65011b577ffSTaylor Simpson int pnum, TCGCond cond, TCGv arg1, int arg2, 65111b577ffSTaylor Simpson int pc_off) 65211b577ffSTaylor Simpson { 65311b577ffSTaylor Simpson TCGv tmp = tcg_constant_tl(arg2); 65411b577ffSTaylor Simpson gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off); 65511b577ffSTaylor Simpson } 65611b577ffSTaylor Simpson 65711b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond, 65811b577ffSTaylor Simpson TCGv arg, int pc_off) 65911b577ffSTaylor Simpson { 66011b577ffSTaylor Simpson gen_cmpnd_cmpi_jmp_t(ctx, pnum, cond, arg, -1, pc_off); 66111b577ffSTaylor Simpson } 66211b577ffSTaylor Simpson 66311b577ffSTaylor Simpson static void gen_cmpnd_cmp_n1_jmp_f(DisasContext *ctx, int pnum, TCGCond cond, 66411b577ffSTaylor Simpson TCGv arg, int pc_off) 66511b577ffSTaylor Simpson { 66611b577ffSTaylor Simpson gen_cmpnd_cmpi_jmp_f(ctx, pnum, cond, arg, -1, pc_off); 66711b577ffSTaylor Simpson } 66811b577ffSTaylor Simpson 66911b577ffSTaylor Simpson static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx, 67011b577ffSTaylor Simpson int pnum, TCGv arg, TCGCond cond, int pc_off) 67111b577ffSTaylor Simpson { 67211b577ffSTaylor Simpson if (ctx->insn->part1) { 67311b577ffSTaylor Simpson TCGv pred = tcg_temp_new(); 67411b577ffSTaylor Simpson tcg_gen_andi_tl(pred, arg, 1); 67511b577ffSTaylor Simpson gen_8bitsof(pred, pred); 67611b577ffSTaylor Simpson gen_log_pred_write(ctx, pnum, pred); 67711b577ffSTaylor Simpson } else { 67811b577ffSTaylor Simpson TCGv pred = tcg_temp_new(); 679e22edc7cSTaylor Simpson tcg_gen_mov_tl(pred, ctx->new_pred_value[pnum]); 68011b577ffSTaylor Simpson gen_cond_jump(ctx, cond, pred, pc_off); 68111b577ffSTaylor Simpson } 68211b577ffSTaylor Simpson } 68311b577ffSTaylor Simpson 68497b16fafSTaylor Simpson static void gen_testbit0_jumpnv(DisasContext *ctx, 68597b16fafSTaylor Simpson TCGv arg, TCGCond cond, int pc_off) 68697b16fafSTaylor Simpson { 68797b16fafSTaylor Simpson TCGv pred = tcg_temp_new(); 68897b16fafSTaylor Simpson tcg_gen_andi_tl(pred, arg, 1); 68997b16fafSTaylor Simpson gen_cond_jump(ctx, cond, pred, pc_off); 69097b16fafSTaylor Simpson } 69197b16fafSTaylor Simpson 69297b16fafSTaylor Simpson static void gen_jump(DisasContext *ctx, int pc_off) 69397b16fafSTaylor Simpson { 69497b16fafSTaylor Simpson gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL); 69597b16fafSTaylor Simpson } 69697b16fafSTaylor Simpson 69797b16fafSTaylor Simpson static void gen_jumpr(DisasContext *ctx, TCGv new_pc) 69897b16fafSTaylor Simpson { 69997b16fafSTaylor Simpson gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL); 70097b16fafSTaylor Simpson } 70197b16fafSTaylor Simpson 70261c6c06eSTaylor Simpson static void gen_call(DisasContext *ctx, int pc_off) 70361c6c06eSTaylor Simpson { 704e28b77a6STaylor Simpson TCGv lr = get_result_gpr(ctx, HEX_REG_LR); 705e28b77a6STaylor Simpson tcg_gen_movi_tl(lr, ctx->next_PC); 70661c6c06eSTaylor Simpson gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL); 70761c6c06eSTaylor Simpson } 70861c6c06eSTaylor Simpson 709242af2c0STaylor Simpson static void gen_callr(DisasContext *ctx, TCGv new_pc) 710242af2c0STaylor Simpson { 711e28b77a6STaylor Simpson TCGv lr = get_result_gpr(ctx, HEX_REG_LR); 712e28b77a6STaylor Simpson tcg_gen_movi_tl(lr, ctx->next_PC); 713242af2c0STaylor Simpson gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL); 714242af2c0STaylor Simpson } 715242af2c0STaylor Simpson 71661c6c06eSTaylor Simpson static void gen_cond_call(DisasContext *ctx, TCGv pred, 71761c6c06eSTaylor Simpson TCGCond cond, int pc_off) 71861c6c06eSTaylor Simpson { 719e28b77a6STaylor Simpson TCGv lr = get_result_gpr(ctx, HEX_REG_LR); 7207a819de8SRichard Henderson TCGv lsb = tcg_temp_new(); 72161c6c06eSTaylor Simpson TCGLabel *skip = gen_new_label(); 72261c6c06eSTaylor Simpson tcg_gen_andi_tl(lsb, pred, 1); 72361c6c06eSTaylor Simpson gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb); 72461c6c06eSTaylor Simpson tcg_gen_brcondi_tl(cond, lsb, 0, skip); 725e28b77a6STaylor Simpson tcg_gen_movi_tl(lr, ctx->next_PC); 72661c6c06eSTaylor Simpson gen_set_label(skip); 72761c6c06eSTaylor Simpson } 72861c6c06eSTaylor Simpson 729242af2c0STaylor Simpson static void gen_cond_callr(DisasContext *ctx, 730242af2c0STaylor Simpson TCGCond cond, TCGv pred, TCGv new_pc) 731242af2c0STaylor Simpson { 732242af2c0STaylor Simpson TCGv lsb = tcg_temp_new(); 733242af2c0STaylor Simpson TCGLabel *skip = gen_new_label(); 734242af2c0STaylor Simpson tcg_gen_andi_tl(lsb, pred, 1); 735242af2c0STaylor Simpson tcg_gen_brcondi_tl(cond, lsb, 0, skip); 736242af2c0STaylor Simpson gen_callr(ctx, new_pc); 737242af2c0STaylor Simpson gen_set_label(skip); 738242af2c0STaylor Simpson } 739242af2c0STaylor Simpson 740085b6700STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER 741085b6700STaylor Simpson /* frame = ((LR << 32) | FP) ^ (FRAMEKEY << 32)) */ 742085b6700STaylor Simpson static TCGv_i64 gen_frame_scramble(void) 743085b6700STaylor Simpson { 744085b6700STaylor Simpson TCGv_i64 frame = tcg_temp_new_i64(); 745085b6700STaylor Simpson TCGv tmp = tcg_temp_new(); 746085b6700STaylor Simpson tcg_gen_xor_tl(tmp, hex_gpr[HEX_REG_LR], hex_gpr[HEX_REG_FRAMEKEY]); 747085b6700STaylor Simpson tcg_gen_concat_i32_i64(frame, hex_gpr[HEX_REG_FP], tmp); 748085b6700STaylor Simpson return frame; 749085b6700STaylor Simpson } 750085b6700STaylor Simpson #endif 751085b6700STaylor Simpson 752dae386b8STaylor Simpson /* frame ^= (int64_t)FRAMEKEY << 32 */ 753dae386b8STaylor Simpson static void gen_frame_unscramble(TCGv_i64 frame) 754dae386b8STaylor Simpson { 755dae386b8STaylor Simpson TCGv_i64 framekey = tcg_temp_new_i64(); 756dae386b8STaylor Simpson tcg_gen_extu_i32_i64(framekey, hex_gpr[HEX_REG_FRAMEKEY]); 757dae386b8STaylor Simpson tcg_gen_shli_i64(framekey, framekey, 32); 758dae386b8STaylor Simpson tcg_gen_xor_i64(frame, frame, framekey); 759dae386b8STaylor Simpson } 760dae386b8STaylor Simpson 761dae386b8STaylor Simpson static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA) 762dae386b8STaylor Simpson { 763dae386b8STaylor Simpson Insn *insn = ctx->insn; /* Needed for CHECK_NOSHUF */ 764dae386b8STaylor Simpson CHECK_NOSHUF(EA, 8); 76553b26d25SRichard Henderson tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ); 766dae386b8STaylor Simpson } 767dae386b8STaylor Simpson 768085b6700STaylor Simpson #ifndef CONFIG_HEXAGON_IDEF_PARSER 769085b6700STaylor Simpson /* Stack overflow check */ 770085b6700STaylor Simpson static void gen_framecheck(TCGv EA, int framesize) 771085b6700STaylor Simpson { 772085b6700STaylor Simpson /* Not modelled in linux-user mode */ 773085b6700STaylor Simpson /* Placeholder for system mode */ 774085b6700STaylor Simpson #ifndef CONFIG_USER_ONLY 775085b6700STaylor Simpson g_assert_not_reached(); 776085b6700STaylor Simpson #endif 777085b6700STaylor Simpson } 778085b6700STaylor Simpson 779085b6700STaylor Simpson static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize) 780085b6700STaylor Simpson { 781085b6700STaylor Simpson TCGv r30 = tcg_temp_new(); 782085b6700STaylor Simpson TCGv_i64 frame; 783085b6700STaylor Simpson tcg_gen_addi_tl(r30, r29, -8); 784085b6700STaylor Simpson frame = gen_frame_scramble(); 785085b6700STaylor Simpson gen_store8(cpu_env, r30, frame, ctx->insn->slot); 786085b6700STaylor Simpson gen_log_reg_write(ctx, HEX_REG_FP, r30); 787085b6700STaylor Simpson gen_framecheck(r30, framesize); 788085b6700STaylor Simpson tcg_gen_subi_tl(r29, r30, framesize); 789085b6700STaylor Simpson } 790085b6700STaylor Simpson 791085b6700STaylor Simpson static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30) 792085b6700STaylor Simpson { 793085b6700STaylor Simpson TCGv r29 = tcg_temp_new(); 794085b6700STaylor Simpson TCGv_i64 frame = tcg_temp_new_i64(); 795085b6700STaylor Simpson gen_load_frame(ctx, frame, r30); 796085b6700STaylor Simpson gen_frame_unscramble(frame); 797085b6700STaylor Simpson tcg_gen_mov_i64(r31_30, frame); 798085b6700STaylor Simpson tcg_gen_addi_tl(r29, r30, 8); 799085b6700STaylor Simpson gen_log_reg_write(ctx, HEX_REG_SP, r29); 800085b6700STaylor Simpson } 801085b6700STaylor Simpson #endif 802085b6700STaylor Simpson 803e28b77a6STaylor Simpson static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src) 804dae386b8STaylor Simpson { 805dae386b8STaylor Simpson /* 806dae386b8STaylor Simpson * frame = *src 807dae386b8STaylor Simpson * dst = frame_unscramble(frame) 808dae386b8STaylor Simpson * SP = src + 8 809dae386b8STaylor Simpson * PC = dst.w[1] 810dae386b8STaylor Simpson */ 811dae386b8STaylor Simpson TCGv_i64 frame = tcg_temp_new_i64(); 812dae386b8STaylor Simpson TCGv r31 = tcg_temp_new(); 813e28b77a6STaylor Simpson TCGv r29 = get_result_gpr(ctx, HEX_REG_SP); 814dae386b8STaylor Simpson 815dae386b8STaylor Simpson gen_load_frame(ctx, frame, src); 816dae386b8STaylor Simpson gen_frame_unscramble(frame); 817dae386b8STaylor Simpson tcg_gen_mov_i64(dst, frame); 818dae386b8STaylor Simpson tcg_gen_addi_tl(r29, src, 8); 819dae386b8STaylor Simpson tcg_gen_extrh_i64_i32(r31, dst); 820dae386b8STaylor Simpson gen_jumpr(ctx, r31); 821dae386b8STaylor Simpson } 822dae386b8STaylor Simpson 823dae386b8STaylor Simpson /* if (pred) dst = dealloc_return(src):raw */ 824dae386b8STaylor Simpson static void gen_cond_return(DisasContext *ctx, TCGv_i64 dst, TCGv src, 825dae386b8STaylor Simpson TCGv pred, TCGCond cond) 826dae386b8STaylor Simpson { 827dae386b8STaylor Simpson TCGv LSB = tcg_temp_new(); 828dae386b8STaylor Simpson TCGLabel *skip = gen_new_label(); 829dae386b8STaylor Simpson tcg_gen_andi_tl(LSB, pred, 1); 830dae386b8STaylor Simpson 831dae386b8STaylor Simpson tcg_gen_brcondi_tl(cond, LSB, 0, skip); 832e28b77a6STaylor Simpson gen_return(ctx, dst, src); 833dae386b8STaylor Simpson gen_set_label(skip); 834dae386b8STaylor Simpson } 835dae386b8STaylor Simpson 836dae386b8STaylor Simpson /* sub-instruction version (no RddV, so handle it manually) */ 837dae386b8STaylor Simpson static void gen_cond_return_subinsn(DisasContext *ctx, TCGCond cond, TCGv pred) 838dae386b8STaylor Simpson { 839e28b77a6STaylor Simpson TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP); 840dae386b8STaylor Simpson gen_cond_return(ctx, RddV, hex_gpr[HEX_REG_FP], pred, cond); 84107540a28STaylor Simpson gen_log_reg_write_pair(ctx, HEX_REG_FP, RddV); 842dae386b8STaylor Simpson } 843dae386b8STaylor Simpson 844564b2040STaylor Simpson static void gen_endloop0(DisasContext *ctx) 845564b2040STaylor Simpson { 8467a819de8SRichard Henderson TCGv lpcfg = tcg_temp_new(); 847564b2040STaylor Simpson 848564b2040STaylor Simpson GET_USR_FIELD(USR_LPCFG, lpcfg); 849564b2040STaylor Simpson 850564b2040STaylor Simpson /* 851564b2040STaylor Simpson * if (lpcfg == 1) { 85225e1d87dSTaylor Simpson * p3 = 0xff; 853564b2040STaylor Simpson * } 854564b2040STaylor Simpson */ 855564b2040STaylor Simpson TCGLabel *label1 = gen_new_label(); 856564b2040STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1); 857564b2040STaylor Simpson { 85825e1d87dSTaylor Simpson gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff)); 859564b2040STaylor Simpson } 860564b2040STaylor Simpson gen_set_label(label1); 861564b2040STaylor Simpson 862564b2040STaylor Simpson /* 863564b2040STaylor Simpson * if (lpcfg) { 864564b2040STaylor Simpson * SET_USR_FIELD(USR_LPCFG, lpcfg - 1); 865564b2040STaylor Simpson * } 866564b2040STaylor Simpson */ 867564b2040STaylor Simpson TCGLabel *label2 = gen_new_label(); 868564b2040STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2); 869564b2040STaylor Simpson { 870564b2040STaylor Simpson tcg_gen_subi_tl(lpcfg, lpcfg, 1); 871148ef7fdSTaylor Simpson gen_set_usr_field(ctx, USR_LPCFG, lpcfg); 872564b2040STaylor Simpson } 873564b2040STaylor Simpson gen_set_label(label2); 874564b2040STaylor Simpson 875564b2040STaylor Simpson /* 876564b2040STaylor Simpson * If we're in a tight loop, we'll do this at the end of the TB to take 877564b2040STaylor Simpson * advantage of direct block chaining. 878564b2040STaylor Simpson */ 879564b2040STaylor Simpson if (!ctx->is_tight_loop) { 880564b2040STaylor Simpson /* 881*2babbd93SMatheus Tavares Bernardino * if (LC0 > 1) { 882*2babbd93SMatheus Tavares Bernardino * PC = SA0; 883*2babbd93SMatheus Tavares Bernardino * LC0--; 884564b2040STaylor Simpson * } 885564b2040STaylor Simpson */ 886564b2040STaylor Simpson TCGLabel *label3 = gen_new_label(); 887564b2040STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3); 888564b2040STaylor Simpson { 889e28b77a6STaylor Simpson TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0); 890564b2040STaylor Simpson gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]); 891e28b77a6STaylor Simpson tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1); 892564b2040STaylor Simpson } 893564b2040STaylor Simpson gen_set_label(label3); 894564b2040STaylor Simpson } 895564b2040STaylor Simpson } 896564b2040STaylor Simpson 897b8552a78STaylor Simpson static void gen_endloop1(DisasContext *ctx) 898b8552a78STaylor Simpson { 899b8552a78STaylor Simpson /* 900*2babbd93SMatheus Tavares Bernardino * if (LC1 > 1) { 901*2babbd93SMatheus Tavares Bernardino * PC = SA1; 902*2babbd93SMatheus Tavares Bernardino * LC1--; 903b8552a78STaylor Simpson * } 904b8552a78STaylor Simpson */ 905b8552a78STaylor Simpson TCGLabel *label = gen_new_label(); 906b8552a78STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, label); 907b8552a78STaylor Simpson { 908e28b77a6STaylor Simpson TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1); 909b8552a78STaylor Simpson gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]); 910e28b77a6STaylor Simpson tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1); 911b8552a78STaylor Simpson } 912b8552a78STaylor Simpson gen_set_label(label); 913b8552a78STaylor Simpson } 914b8552a78STaylor Simpson 915b8552a78STaylor Simpson static void gen_endloop01(DisasContext *ctx) 916b8552a78STaylor Simpson { 917b8552a78STaylor Simpson TCGv lpcfg = tcg_temp_new(); 918b8552a78STaylor Simpson TCGLabel *label1 = gen_new_label(); 919b8552a78STaylor Simpson TCGLabel *label2 = gen_new_label(); 920b8552a78STaylor Simpson TCGLabel *label3 = gen_new_label(); 921b8552a78STaylor Simpson TCGLabel *done = gen_new_label(); 922b8552a78STaylor Simpson 923b8552a78STaylor Simpson GET_USR_FIELD(USR_LPCFG, lpcfg); 924b8552a78STaylor Simpson 925b8552a78STaylor Simpson /* 926b8552a78STaylor Simpson * if (lpcfg == 1) { 92725e1d87dSTaylor Simpson * p3 = 0xff; 928b8552a78STaylor Simpson * } 929b8552a78STaylor Simpson */ 930b8552a78STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1); 931b8552a78STaylor Simpson { 93225e1d87dSTaylor Simpson gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff)); 933b8552a78STaylor Simpson } 934b8552a78STaylor Simpson gen_set_label(label1); 935b8552a78STaylor Simpson 936b8552a78STaylor Simpson /* 937b8552a78STaylor Simpson * if (lpcfg) { 938b8552a78STaylor Simpson * SET_USR_FIELD(USR_LPCFG, lpcfg - 1); 939b8552a78STaylor Simpson * } 940b8552a78STaylor Simpson */ 941b8552a78STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2); 942b8552a78STaylor Simpson { 943b8552a78STaylor Simpson tcg_gen_subi_tl(lpcfg, lpcfg, 1); 944148ef7fdSTaylor Simpson gen_set_usr_field(ctx, USR_LPCFG, lpcfg); 945b8552a78STaylor Simpson } 946b8552a78STaylor Simpson gen_set_label(label2); 947b8552a78STaylor Simpson 948b8552a78STaylor Simpson /* 949*2babbd93SMatheus Tavares Bernardino * if (LC0 > 1) { 950*2babbd93SMatheus Tavares Bernardino * PC = SA0; 951*2babbd93SMatheus Tavares Bernardino * LC0--; 952*2babbd93SMatheus Tavares Bernardino * } else if (LC1 > 1) { 953*2babbd93SMatheus Tavares Bernardino * PC = SA1; 954*2babbd93SMatheus Tavares Bernardino * LC1--; 955b8552a78STaylor Simpson * } 956b8552a78STaylor Simpson */ 957b8552a78STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3); 958b8552a78STaylor Simpson { 959e28b77a6STaylor Simpson TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0); 960b8552a78STaylor Simpson gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]); 961e28b77a6STaylor Simpson tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1); 962b8552a78STaylor Simpson tcg_gen_br(done); 963b8552a78STaylor Simpson } 964b8552a78STaylor Simpson gen_set_label(label3); 965b8552a78STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, done); 966b8552a78STaylor Simpson { 967e28b77a6STaylor Simpson TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1); 968b8552a78STaylor Simpson gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]); 969e28b77a6STaylor Simpson tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1); 970b8552a78STaylor Simpson } 971b8552a78STaylor Simpson gen_set_label(done); 972b8552a78STaylor Simpson } 973b8552a78STaylor Simpson 97497b16fafSTaylor Simpson static void gen_cmp_jumpnv(DisasContext *ctx, 97597b16fafSTaylor Simpson TCGCond cond, TCGv val, TCGv src, int pc_off) 97697b16fafSTaylor Simpson { 97797b16fafSTaylor Simpson TCGv pred = tcg_temp_new(); 97897b16fafSTaylor Simpson tcg_gen_setcond_tl(cond, pred, val, src); 97997b16fafSTaylor Simpson gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off); 98097b16fafSTaylor Simpson } 98197b16fafSTaylor Simpson 98297b16fafSTaylor Simpson static void gen_cmpi_jumpnv(DisasContext *ctx, 98397b16fafSTaylor Simpson TCGCond cond, TCGv val, int src, int pc_off) 98497b16fafSTaylor Simpson { 98597b16fafSTaylor Simpson TCGv pred = tcg_temp_new(); 98697b16fafSTaylor Simpson tcg_gen_setcondi_tl(cond, pred, val, src); 98797b16fafSTaylor Simpson gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off); 98897b16fafSTaylor Simpson } 98997b16fafSTaylor Simpson 9908e8a85c1STaylor Simpson /* Shift left with saturation */ 991148ef7fdSTaylor Simpson static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt) 9928e8a85c1STaylor Simpson { 99371ed3697STaylor Simpson TCGv tmp = tcg_temp_new(); /* In case dst == src */ 994148ef7fdSTaylor Simpson TCGv usr = get_result_gpr(ctx, HEX_REG_USR); 9958e8a85c1STaylor Simpson TCGv sh32 = tcg_temp_new(); 9968e8a85c1STaylor Simpson TCGv dst_sar = tcg_temp_new(); 9978e8a85c1STaylor Simpson TCGv ovf = tcg_temp_new(); 9988e8a85c1STaylor Simpson TCGv satval = tcg_temp_new(); 9998e8a85c1STaylor Simpson TCGv min = tcg_constant_tl(0x80000000); 10008e8a85c1STaylor Simpson TCGv max = tcg_constant_tl(0x7fffffff); 10018e8a85c1STaylor Simpson 10028e8a85c1STaylor Simpson /* 10038e8a85c1STaylor Simpson * Possible values for shift_amt are 0 .. 64 10048e8a85c1STaylor Simpson * We need special handling for values above 31 10058e8a85c1STaylor Simpson * 10068e8a85c1STaylor Simpson * sh32 = shift & 31; 10078e8a85c1STaylor Simpson * dst = sh32 == shift ? src : 0; 10088e8a85c1STaylor Simpson * dst <<= sh32; 10098e8a85c1STaylor Simpson * dst_sar = dst >> sh32; 10108e8a85c1STaylor Simpson * satval = src < 0 ? min : max; 10118e8a85c1STaylor Simpson * if (dst_asr != src) { 10128e8a85c1STaylor Simpson * usr.OVF |= 1; 10138e8a85c1STaylor Simpson * dst = satval; 10148e8a85c1STaylor Simpson * } 10158e8a85c1STaylor Simpson */ 10168e8a85c1STaylor Simpson 10178e8a85c1STaylor Simpson tcg_gen_andi_tl(sh32, shift_amt, 31); 101871ed3697STaylor Simpson tcg_gen_movcond_tl(TCG_COND_EQ, tmp, sh32, shift_amt, 10198e8a85c1STaylor Simpson src, tcg_constant_tl(0)); 102071ed3697STaylor Simpson tcg_gen_shl_tl(tmp, tmp, sh32); 102171ed3697STaylor Simpson tcg_gen_sar_tl(dst_sar, tmp, sh32); 10228e8a85c1STaylor Simpson tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max); 10238e8a85c1STaylor Simpson 10248e8a85c1STaylor Simpson tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src); 10258e8a85c1STaylor Simpson tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset); 1026148ef7fdSTaylor Simpson tcg_gen_or_tl(usr, usr, ovf); 10278e8a85c1STaylor Simpson 102871ed3697STaylor Simpson tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, tmp, satval); 10298e8a85c1STaylor Simpson } 10308e8a85c1STaylor Simpson 10318e8a85c1STaylor Simpson static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt) 10328e8a85c1STaylor Simpson { 10338e8a85c1STaylor Simpson /* 10348e8a85c1STaylor Simpson * Shift arithmetic right 10358e8a85c1STaylor Simpson * Robust when shift_amt is >31 bits 10368e8a85c1STaylor Simpson */ 10378e8a85c1STaylor Simpson TCGv tmp = tcg_temp_new(); 10388e8a85c1STaylor Simpson tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31)); 10398e8a85c1STaylor Simpson tcg_gen_sar_tl(dst, src, tmp); 10408e8a85c1STaylor Simpson } 10418e8a85c1STaylor Simpson 10428e8a85c1STaylor Simpson /* Bidirectional shift right with saturation */ 1043148ef7fdSTaylor Simpson static void gen_asr_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV) 10448e8a85c1STaylor Simpson { 10457a819de8SRichard Henderson TCGv shift_amt = tcg_temp_new(); 10468e8a85c1STaylor Simpson TCGLabel *positive = gen_new_label(); 10478e8a85c1STaylor Simpson TCGLabel *done = gen_new_label(); 10488e8a85c1STaylor Simpson 10498e8a85c1STaylor Simpson tcg_gen_sextract_i32(shift_amt, RtV, 0, 7); 10508e8a85c1STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive); 10518e8a85c1STaylor Simpson 10528e8a85c1STaylor Simpson /* Negative shift amount => shift left */ 10538e8a85c1STaylor Simpson tcg_gen_neg_tl(shift_amt, shift_amt); 1054148ef7fdSTaylor Simpson gen_shl_sat(ctx, RdV, RsV, shift_amt); 10558e8a85c1STaylor Simpson tcg_gen_br(done); 10568e8a85c1STaylor Simpson 10578e8a85c1STaylor Simpson gen_set_label(positive); 10588e8a85c1STaylor Simpson /* Positive shift amount => shift right */ 10598e8a85c1STaylor Simpson gen_sar(RdV, RsV, shift_amt); 10608e8a85c1STaylor Simpson 10618e8a85c1STaylor Simpson gen_set_label(done); 10628e8a85c1STaylor Simpson } 10638e8a85c1STaylor Simpson 10648e8a85c1STaylor Simpson /* Bidirectional shift left with saturation */ 1065148ef7fdSTaylor Simpson static void gen_asl_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV) 10668e8a85c1STaylor Simpson { 10677a819de8SRichard Henderson TCGv shift_amt = tcg_temp_new(); 10688e8a85c1STaylor Simpson TCGLabel *positive = gen_new_label(); 10698e8a85c1STaylor Simpson TCGLabel *done = gen_new_label(); 10708e8a85c1STaylor Simpson 10718e8a85c1STaylor Simpson tcg_gen_sextract_i32(shift_amt, RtV, 0, 7); 10728e8a85c1STaylor Simpson tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive); 10738e8a85c1STaylor Simpson 10748e8a85c1STaylor Simpson /* Negative shift amount => shift right */ 10758e8a85c1STaylor Simpson tcg_gen_neg_tl(shift_amt, shift_amt); 10768e8a85c1STaylor Simpson gen_sar(RdV, RsV, shift_amt); 10778e8a85c1STaylor Simpson tcg_gen_br(done); 10788e8a85c1STaylor Simpson 10798e8a85c1STaylor Simpson gen_set_label(positive); 10808e8a85c1STaylor Simpson /* Positive shift amount => shift left */ 1081148ef7fdSTaylor Simpson gen_shl_sat(ctx, RdV, RsV, shift_amt); 10828e8a85c1STaylor Simpson 10838e8a85c1STaylor Simpson gen_set_label(done); 10848e8a85c1STaylor Simpson } 10858e8a85c1STaylor Simpson 108600e64fdaSTaylor Simpson static void gen_insert_rp(DisasContext *ctx, TCGv RxV, TCGv RsV, TCGv_i64 RttV) 108700e64fdaSTaylor Simpson { 108800e64fdaSTaylor Simpson /* 108900e64fdaSTaylor Simpson * int width = fZXTN(6, 32, (fGETWORD(1, RttV))); 109000e64fdaSTaylor Simpson * int offset = fSXTN(7, 32, (fGETWORD(0, RttV))); 109100e64fdaSTaylor Simpson * size8u_t mask = ((fCONSTLL(1) << width) - 1); 109200e64fdaSTaylor Simpson * if (offset < 0) { 109300e64fdaSTaylor Simpson * RxV = 0; 109400e64fdaSTaylor Simpson * } else { 109500e64fdaSTaylor Simpson * RxV &= ~(mask << offset); 109600e64fdaSTaylor Simpson * RxV |= ((RsV & mask) << offset); 109700e64fdaSTaylor Simpson * } 109800e64fdaSTaylor Simpson */ 109900e64fdaSTaylor Simpson 110000e64fdaSTaylor Simpson TCGv width = tcg_temp_new(); 110100e64fdaSTaylor Simpson TCGv offset = tcg_temp_new(); 110200e64fdaSTaylor Simpson TCGv_i64 mask = tcg_temp_new_i64(); 110300e64fdaSTaylor Simpson TCGv_i64 result = tcg_temp_new_i64(); 110400e64fdaSTaylor Simpson TCGv_i64 tmp = tcg_temp_new_i64(); 110500e64fdaSTaylor Simpson TCGv_i64 offset64 = tcg_temp_new_i64(); 110600e64fdaSTaylor Simpson TCGLabel *label = gen_new_label(); 110700e64fdaSTaylor Simpson TCGLabel *done = gen_new_label(); 110800e64fdaSTaylor Simpson 110900e64fdaSTaylor Simpson tcg_gen_extrh_i64_i32(width, RttV); 111000e64fdaSTaylor Simpson tcg_gen_extract_tl(width, width, 0, 6); 111100e64fdaSTaylor Simpson tcg_gen_extrl_i64_i32(offset, RttV); 111200e64fdaSTaylor Simpson tcg_gen_sextract_tl(offset, offset, 0, 7); 111300e64fdaSTaylor Simpson /* Possible values for offset are -64 .. 63 */ 111400e64fdaSTaylor Simpson tcg_gen_brcondi_tl(TCG_COND_GE, offset, 0, label); 111500e64fdaSTaylor Simpson /* For negative offsets, zero out the result */ 111600e64fdaSTaylor Simpson tcg_gen_movi_tl(RxV, 0); 111700e64fdaSTaylor Simpson tcg_gen_br(done); 111800e64fdaSTaylor Simpson gen_set_label(label); 111900e64fdaSTaylor Simpson /* At this point, possible values of offset are 0 .. 63 */ 112000e64fdaSTaylor Simpson tcg_gen_ext_i32_i64(mask, width); 112100e64fdaSTaylor Simpson tcg_gen_shl_i64(mask, tcg_constant_i64(1), mask); 112200e64fdaSTaylor Simpson tcg_gen_subi_i64(mask, mask, 1); 112300e64fdaSTaylor Simpson tcg_gen_extu_i32_i64(result, RxV); 112400e64fdaSTaylor Simpson tcg_gen_ext_i32_i64(tmp, offset); 112500e64fdaSTaylor Simpson tcg_gen_shl_i64(tmp, mask, tmp); 112600e64fdaSTaylor Simpson tcg_gen_andc_i64(result, result, tmp); 112700e64fdaSTaylor Simpson tcg_gen_extu_i32_i64(tmp, RsV); 112800e64fdaSTaylor Simpson tcg_gen_and_i64(tmp, tmp, mask); 112900e64fdaSTaylor Simpson tcg_gen_extu_i32_i64(offset64, offset); 113000e64fdaSTaylor Simpson tcg_gen_shl_i64(tmp, tmp, offset64); 113100e64fdaSTaylor Simpson tcg_gen_or_i64(result, result, tmp); 113200e64fdaSTaylor Simpson tcg_gen_extrl_i64_i32(RxV, result); 113300e64fdaSTaylor Simpson gen_set_label(done); 113400e64fdaSTaylor Simpson } 113500e64fdaSTaylor Simpson 113600e64fdaSTaylor Simpson static void gen_asr_r_svw_trun(DisasContext *ctx, TCGv RdV, 113700e64fdaSTaylor Simpson TCGv_i64 RssV, TCGv RtV) 113800e64fdaSTaylor Simpson { 113900e64fdaSTaylor Simpson /* 114000e64fdaSTaylor Simpson * for (int i = 0; i < 2; i++) { 114100e64fdaSTaylor Simpson * fSETHALF(i, RdV, fGETHALF(0, ((fSXTN(7, 32, RtV) > 0) ? 114200e64fdaSTaylor Simpson * (fCAST4_8s(fGETWORD(i, RssV)) >> fSXTN(7, 32, RtV)) : 114300e64fdaSTaylor Simpson * (fCAST4_8s(fGETWORD(i, RssV)) << -fSXTN(7, 32, RtV))))); 114400e64fdaSTaylor Simpson * } 114500e64fdaSTaylor Simpson */ 114600e64fdaSTaylor Simpson TCGv shift_amt32 = tcg_temp_new(); 114700e64fdaSTaylor Simpson TCGv_i64 shift_amt64 = tcg_temp_new_i64(); 114800e64fdaSTaylor Simpson TCGv_i64 tmp64 = tcg_temp_new_i64(); 114900e64fdaSTaylor Simpson TCGv tmp32 = tcg_temp_new(); 115000e64fdaSTaylor Simpson TCGLabel *label = gen_new_label(); 115100e64fdaSTaylor Simpson TCGLabel *zero = gen_new_label(); 115200e64fdaSTaylor Simpson TCGLabel *done = gen_new_label(); 115300e64fdaSTaylor Simpson 115400e64fdaSTaylor Simpson tcg_gen_sextract_tl(shift_amt32, RtV, 0, 7); 115500e64fdaSTaylor Simpson /* Possible values of shift_amt32 are -64 .. 63 */ 115600e64fdaSTaylor Simpson tcg_gen_brcondi_tl(TCG_COND_LE, shift_amt32, 0, label); 115700e64fdaSTaylor Simpson /* After branch, possible values of shift_amt32 are 1 .. 63 */ 115800e64fdaSTaylor Simpson tcg_gen_ext_i32_i64(shift_amt64, shift_amt32); 115900e64fdaSTaylor Simpson for (int i = 0; i < 2; i++) { 116000e64fdaSTaylor Simpson tcg_gen_sextract_i64(tmp64, RssV, i * 32, 32); 116100e64fdaSTaylor Simpson tcg_gen_sar_i64(tmp64, tmp64, shift_amt64); 116200e64fdaSTaylor Simpson tcg_gen_extrl_i64_i32(tmp32, tmp64); 116300e64fdaSTaylor Simpson tcg_gen_deposit_tl(RdV, RdV, tmp32, i * 16, 16); 116400e64fdaSTaylor Simpson } 116500e64fdaSTaylor Simpson tcg_gen_br(done); 116600e64fdaSTaylor Simpson gen_set_label(label); 116700e64fdaSTaylor Simpson tcg_gen_neg_tl(shift_amt32, shift_amt32); 116800e64fdaSTaylor Simpson /*At this point, possible values of shift_amt32 are 0 .. 64 */ 116900e64fdaSTaylor Simpson tcg_gen_brcondi_tl(TCG_COND_GT, shift_amt32, 63, zero); 117000e64fdaSTaylor Simpson /*At this point, possible values of shift_amt32 are 0 .. 63 */ 117100e64fdaSTaylor Simpson tcg_gen_ext_i32_i64(shift_amt64, shift_amt32); 117200e64fdaSTaylor Simpson for (int i = 0; i < 2; i++) { 117300e64fdaSTaylor Simpson tcg_gen_sextract_i64(tmp64, RssV, i * 32, 32); 117400e64fdaSTaylor Simpson tcg_gen_shl_i64(tmp64, tmp64, shift_amt64); 117500e64fdaSTaylor Simpson tcg_gen_extrl_i64_i32(tmp32, tmp64); 117600e64fdaSTaylor Simpson tcg_gen_deposit_tl(RdV, RdV, tmp32, i * 16, 16); 117700e64fdaSTaylor Simpson } 117800e64fdaSTaylor Simpson tcg_gen_br(done); 117900e64fdaSTaylor Simpson gen_set_label(zero); 118000e64fdaSTaylor Simpson /* When the shift_amt is 64, zero out the result */ 118100e64fdaSTaylor Simpson tcg_gen_movi_tl(RdV, 0); 118200e64fdaSTaylor Simpson gen_set_label(done); 118300e64fdaSTaylor Simpson } 118400e64fdaSTaylor Simpson 1185887d61b2STaylor Simpson static intptr_t vreg_src_off(DisasContext *ctx, int num) 1186887d61b2STaylor Simpson { 1187887d61b2STaylor Simpson intptr_t offset = offsetof(CPUHexagonState, VRegs[num]); 1188887d61b2STaylor Simpson 1189887d61b2STaylor Simpson if (test_bit(num, ctx->vregs_select)) { 1190887d61b2STaylor Simpson offset = ctx_future_vreg_off(ctx, num, 1, false); 1191887d61b2STaylor Simpson } 1192887d61b2STaylor Simpson if (test_bit(num, ctx->vregs_updated_tmp)) { 1193887d61b2STaylor Simpson offset = ctx_tmp_vreg_off(ctx, num, 1, false); 1194887d61b2STaylor Simpson } 1195887d61b2STaylor Simpson return offset; 1196887d61b2STaylor Simpson } 1197887d61b2STaylor Simpson 1198887d61b2STaylor Simpson static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num, 1199c2b33d0bSTaylor Simpson VRegWriteType type) 1200887d61b2STaylor Simpson { 1201887d61b2STaylor Simpson intptr_t dstoff; 1202887d61b2STaylor Simpson 1203887d61b2STaylor Simpson if (type != EXT_TMP) { 1204887d61b2STaylor Simpson dstoff = ctx_future_vreg_off(ctx, num, 1, true); 1205887d61b2STaylor Simpson tcg_gen_gvec_mov(MO_64, dstoff, srcoff, 1206887d61b2STaylor Simpson sizeof(MMVector), sizeof(MMVector)); 1207887d61b2STaylor Simpson } else { 1208887d61b2STaylor Simpson dstoff = ctx_tmp_vreg_off(ctx, num, 1, false); 1209887d61b2STaylor Simpson tcg_gen_gvec_mov(MO_64, dstoff, srcoff, 1210887d61b2STaylor Simpson sizeof(MMVector), sizeof(MMVector)); 1211887d61b2STaylor Simpson } 1212887d61b2STaylor Simpson } 1213887d61b2STaylor Simpson 1214887d61b2STaylor Simpson static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num, 1215c2b33d0bSTaylor Simpson VRegWriteType type) 1216887d61b2STaylor Simpson { 1217c2b33d0bSTaylor Simpson gen_log_vreg_write(ctx, srcoff, num ^ 0, type); 1218887d61b2STaylor Simpson srcoff += sizeof(MMVector); 1219c2b33d0bSTaylor Simpson gen_log_vreg_write(ctx, srcoff, num ^ 1, type); 1220887d61b2STaylor Simpson } 1221887d61b2STaylor Simpson 1222c2b33d0bSTaylor Simpson static intptr_t get_result_qreg(DisasContext *ctx, int qnum) 1223887d61b2STaylor Simpson { 1224b8552985STaylor Simpson if (ctx->need_commit) { 1225c2b33d0bSTaylor Simpson return offsetof(CPUHexagonState, future_QRegs[qnum]); 1226b8552985STaylor Simpson } else { 1227b8552985STaylor Simpson return offsetof(CPUHexagonState, QRegs[qnum]); 1228b8552985STaylor Simpson } 1229887d61b2STaylor Simpson } 1230887d61b2STaylor Simpson 1231887d61b2STaylor Simpson static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src, 1232887d61b2STaylor Simpson bool aligned) 1233887d61b2STaylor Simpson { 1234887d61b2STaylor Simpson TCGv_i64 tmp = tcg_temp_new_i64(); 1235887d61b2STaylor Simpson if (aligned) { 1236887d61b2STaylor Simpson tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1)); 1237887d61b2STaylor Simpson } 1238887d61b2STaylor Simpson for (int i = 0; i < sizeof(MMVector) / 8; i++) { 123953b26d25SRichard Henderson tcg_gen_qemu_ld_i64(tmp, src, ctx->mem_idx, MO_TEUQ); 1240887d61b2STaylor Simpson tcg_gen_addi_tl(src, src, 8); 1241887d61b2STaylor Simpson tcg_gen_st_i64(tmp, cpu_env, dstoff + i * 8); 1242887d61b2STaylor Simpson } 1243887d61b2STaylor Simpson } 1244887d61b2STaylor Simpson 12451e536334STaylor Simpson static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff, 12461e536334STaylor Simpson int slot, bool aligned) 1247887d61b2STaylor Simpson { 1248887d61b2STaylor Simpson intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data); 1249887d61b2STaylor Simpson intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask); 1250887d61b2STaylor Simpson 12511e536334STaylor Simpson if (is_gather_store_insn(ctx)) { 1252887d61b2STaylor Simpson TCGv sl = tcg_constant_tl(slot); 1253887d61b2STaylor Simpson gen_helper_gather_store(cpu_env, EA, sl); 1254887d61b2STaylor Simpson return; 1255887d61b2STaylor Simpson } 1256887d61b2STaylor Simpson 1257887d61b2STaylor Simpson tcg_gen_movi_tl(hex_vstore_pending[slot], 1); 1258887d61b2STaylor Simpson if (aligned) { 1259887d61b2STaylor Simpson tcg_gen_andi_tl(hex_vstore_addr[slot], EA, 1260887d61b2STaylor Simpson ~((int32_t)sizeof(MMVector) - 1)); 1261887d61b2STaylor Simpson } else { 1262887d61b2STaylor Simpson tcg_gen_mov_tl(hex_vstore_addr[slot], EA); 1263887d61b2STaylor Simpson } 1264887d61b2STaylor Simpson tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector)); 1265887d61b2STaylor Simpson 1266887d61b2STaylor Simpson /* Copy the data to the vstore buffer */ 1267887d61b2STaylor Simpson tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector)); 1268887d61b2STaylor Simpson /* Set the mask to all 1's */ 1269887d61b2STaylor Simpson tcg_gen_gvec_dup_imm(MO_64, maskoff, sizeof(MMQReg), sizeof(MMQReg), ~0LL); 1270887d61b2STaylor Simpson } 1271887d61b2STaylor Simpson 1272887d61b2STaylor Simpson static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff, 1273887d61b2STaylor Simpson intptr_t bitsoff, int slot, bool invert) 1274887d61b2STaylor Simpson { 1275887d61b2STaylor Simpson intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data); 1276887d61b2STaylor Simpson intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask); 1277887d61b2STaylor Simpson 1278887d61b2STaylor Simpson tcg_gen_movi_tl(hex_vstore_pending[slot], 1); 1279887d61b2STaylor Simpson tcg_gen_andi_tl(hex_vstore_addr[slot], EA, 1280887d61b2STaylor Simpson ~((int32_t)sizeof(MMVector) - 1)); 1281887d61b2STaylor Simpson tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector)); 1282887d61b2STaylor Simpson 1283887d61b2STaylor Simpson /* Copy the data to the vstore buffer */ 1284887d61b2STaylor Simpson tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector)); 1285887d61b2STaylor Simpson /* Copy the mask */ 1286887d61b2STaylor Simpson tcg_gen_gvec_mov(MO_64, maskoff, bitsoff, sizeof(MMQReg), sizeof(MMQReg)); 1287887d61b2STaylor Simpson if (invert) { 1288887d61b2STaylor Simpson tcg_gen_gvec_not(MO_64, maskoff, maskoff, 1289887d61b2STaylor Simpson sizeof(MMQReg), sizeof(MMQReg)); 1290887d61b2STaylor Simpson } 1291887d61b2STaylor Simpson } 1292887d61b2STaylor Simpson 1293887d61b2STaylor Simpson static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff) 1294887d61b2STaylor Simpson { 1295887d61b2STaylor Simpson TCGv_i64 tmp = tcg_temp_new_i64(); 1296887d61b2STaylor Simpson TCGv_i64 word = tcg_temp_new_i64(); 1297887d61b2STaylor Simpson TCGv_i64 bits = tcg_temp_new_i64(); 1298887d61b2STaylor Simpson TCGv_i64 mask = tcg_temp_new_i64(); 1299887d61b2STaylor Simpson TCGv_i64 zero = tcg_constant_i64(0); 1300887d61b2STaylor Simpson TCGv_i64 ones = tcg_constant_i64(~0); 1301887d61b2STaylor Simpson 1302887d61b2STaylor Simpson for (int i = 0; i < sizeof(MMVector) / 8; i++) { 1303887d61b2STaylor Simpson tcg_gen_ld_i64(tmp, cpu_env, srcoff + i * 8); 1304887d61b2STaylor Simpson tcg_gen_movi_i64(mask, 0); 1305887d61b2STaylor Simpson 1306887d61b2STaylor Simpson for (int j = 0; j < 8; j += size) { 1307887d61b2STaylor Simpson tcg_gen_extract_i64(word, tmp, j * 8, size * 8); 1308887d61b2STaylor Simpson tcg_gen_movcond_i64(TCG_COND_NE, bits, word, zero, ones, zero); 1309887d61b2STaylor Simpson tcg_gen_deposit_i64(mask, mask, bits, j, size); 1310887d61b2STaylor Simpson } 1311887d61b2STaylor Simpson 1312887d61b2STaylor Simpson tcg_gen_st8_i64(mask, cpu_env, dstoff + i); 1313887d61b2STaylor Simpson } 1314887d61b2STaylor Simpson } 1315887d61b2STaylor Simpson 13167e8b3b39SPaolo Montesel void probe_noshuf_load(TCGv va, int s, int mi) 131715fc6badSTaylor Simpson { 131815fc6badSTaylor Simpson TCGv size = tcg_constant_tl(s); 131915fc6badSTaylor Simpson TCGv mem_idx = tcg_constant_tl(mi); 132015fc6badSTaylor Simpson gen_helper_probe_noshuf_load(cpu_env, va, size, mem_idx); 132115fc6badSTaylor Simpson } 132215fc6badSTaylor Simpson 132342659e04SNiccolò Izzo /* 132442659e04SNiccolò Izzo * Note: Since this function might branch, `val` is 132542659e04SNiccolò Izzo * required to be a `tcg_temp_local`. 132642659e04SNiccolò Izzo */ 1327148ef7fdSTaylor Simpson void gen_set_usr_field_if(DisasContext *ctx, int field, TCGv val) 132842659e04SNiccolò Izzo { 132942659e04SNiccolò Izzo /* Sets the USR field if `val` is non-zero */ 133042659e04SNiccolò Izzo if (reg_field_info[field].width == 1) { 1331148ef7fdSTaylor Simpson TCGv usr = get_result_gpr(ctx, HEX_REG_USR); 133242659e04SNiccolò Izzo TCGv tmp = tcg_temp_new(); 133342659e04SNiccolò Izzo tcg_gen_extract_tl(tmp, val, 0, reg_field_info[field].width); 133442659e04SNiccolò Izzo tcg_gen_shli_tl(tmp, tmp, reg_field_info[field].offset); 1335148ef7fdSTaylor Simpson tcg_gen_or_tl(usr, usr, tmp); 133642659e04SNiccolò Izzo } else { 133742659e04SNiccolò Izzo TCGLabel *skip_label = gen_new_label(); 133842659e04SNiccolò Izzo tcg_gen_brcondi_tl(TCG_COND_EQ, val, 0, skip_label); 1339148ef7fdSTaylor Simpson gen_set_usr_field(ctx, field, val); 134042659e04SNiccolò Izzo gen_set_label(skip_label); 134142659e04SNiccolò Izzo } 134242659e04SNiccolò Izzo } 134342659e04SNiccolò Izzo 134442659e04SNiccolò Izzo void gen_sat_i32(TCGv dest, TCGv source, int width) 134542659e04SNiccolò Izzo { 134642659e04SNiccolò Izzo TCGv max_val = tcg_constant_tl((1 << (width - 1)) - 1); 134742659e04SNiccolò Izzo TCGv min_val = tcg_constant_tl(-(1 << (width - 1))); 134842659e04SNiccolò Izzo tcg_gen_smin_tl(dest, source, max_val); 134942659e04SNiccolò Izzo tcg_gen_smax_tl(dest, dest, min_val); 135042659e04SNiccolò Izzo } 135142659e04SNiccolò Izzo 135242659e04SNiccolò Izzo void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width) 135342659e04SNiccolò Izzo { 135471ed3697STaylor Simpson TCGv tmp = tcg_temp_new(); /* In case dest == source */ 135571ed3697STaylor Simpson gen_sat_i32(tmp, source, width); 135671ed3697STaylor Simpson tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp); 135771ed3697STaylor Simpson tcg_gen_mov_tl(dest, tmp); 135842659e04SNiccolò Izzo } 135942659e04SNiccolò Izzo 136042659e04SNiccolò Izzo void gen_satu_i32(TCGv dest, TCGv source, int width) 136142659e04SNiccolò Izzo { 136271ed3697STaylor Simpson TCGv tmp = tcg_temp_new(); /* In case dest == source */ 136342659e04SNiccolò Izzo TCGv max_val = tcg_constant_tl((1 << width) - 1); 136442659e04SNiccolò Izzo TCGv zero = tcg_constant_tl(0); 136571ed3697STaylor Simpson tcg_gen_movcond_tl(TCG_COND_GTU, tmp, source, max_val, max_val, source); 136671ed3697STaylor Simpson tcg_gen_movcond_tl(TCG_COND_LT, tmp, source, zero, zero, tmp); 136771ed3697STaylor Simpson tcg_gen_mov_tl(dest, tmp); 136842659e04SNiccolò Izzo } 136942659e04SNiccolò Izzo 137042659e04SNiccolò Izzo void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width) 137142659e04SNiccolò Izzo { 137271ed3697STaylor Simpson TCGv tmp = tcg_temp_new(); /* In case dest == source */ 137371ed3697STaylor Simpson gen_satu_i32(tmp, source, width); 137471ed3697STaylor Simpson tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp); 137571ed3697STaylor Simpson tcg_gen_mov_tl(dest, tmp); 137642659e04SNiccolò Izzo } 137742659e04SNiccolò Izzo 137842659e04SNiccolò Izzo void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width) 137942659e04SNiccolò Izzo { 138042659e04SNiccolò Izzo TCGv_i64 max_val = tcg_constant_i64((1LL << (width - 1)) - 1LL); 138142659e04SNiccolò Izzo TCGv_i64 min_val = tcg_constant_i64(-(1LL << (width - 1))); 138242659e04SNiccolò Izzo tcg_gen_smin_i64(dest, source, max_val); 138342659e04SNiccolò Izzo tcg_gen_smax_i64(dest, dest, min_val); 138442659e04SNiccolò Izzo } 138542659e04SNiccolò Izzo 138642659e04SNiccolò Izzo void gen_sat_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width) 138742659e04SNiccolò Izzo { 138871ed3697STaylor Simpson TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */ 138942659e04SNiccolò Izzo TCGv_i64 ovfl_64; 139071ed3697STaylor Simpson gen_sat_i64(tmp, source, width); 139142659e04SNiccolò Izzo ovfl_64 = tcg_temp_new_i64(); 139271ed3697STaylor Simpson tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source); 139371ed3697STaylor Simpson tcg_gen_mov_i64(dest, tmp); 139442659e04SNiccolò Izzo tcg_gen_trunc_i64_tl(ovfl, ovfl_64); 139542659e04SNiccolò Izzo } 139642659e04SNiccolò Izzo 139742659e04SNiccolò Izzo void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width) 139842659e04SNiccolò Izzo { 139971ed3697STaylor Simpson TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */ 140042659e04SNiccolò Izzo TCGv_i64 max_val = tcg_constant_i64((1LL << width) - 1LL); 140142659e04SNiccolò Izzo TCGv_i64 zero = tcg_constant_i64(0); 140271ed3697STaylor Simpson tcg_gen_movcond_i64(TCG_COND_GTU, tmp, source, max_val, max_val, source); 140371ed3697STaylor Simpson tcg_gen_movcond_i64(TCG_COND_LT, tmp, source, zero, zero, tmp); 140471ed3697STaylor Simpson tcg_gen_mov_i64(dest, tmp); 140542659e04SNiccolò Izzo } 140642659e04SNiccolò Izzo 140742659e04SNiccolò Izzo void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width) 140842659e04SNiccolò Izzo { 140971ed3697STaylor Simpson TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */ 141042659e04SNiccolò Izzo TCGv_i64 ovfl_64; 141171ed3697STaylor Simpson gen_satu_i64(tmp, source, width); 141242659e04SNiccolò Izzo ovfl_64 = tcg_temp_new_i64(); 141371ed3697STaylor Simpson tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source); 141471ed3697STaylor Simpson tcg_gen_mov_i64(dest, tmp); 141542659e04SNiccolò Izzo tcg_gen_trunc_i64_tl(ovfl, ovfl_64); 141642659e04SNiccolò Izzo } 141742659e04SNiccolò Izzo 141842659e04SNiccolò Izzo /* Implements the fADDSAT64 macro in TCG */ 1419148ef7fdSTaylor Simpson void gen_add_sat_i64(DisasContext *ctx, TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 142042659e04SNiccolò Izzo { 14217a819de8SRichard Henderson TCGv_i64 sum = tcg_temp_new_i64(); 142242659e04SNiccolò Izzo TCGv_i64 xor = tcg_temp_new_i64(); 142342659e04SNiccolò Izzo TCGv_i64 cond1 = tcg_temp_new_i64(); 14247a819de8SRichard Henderson TCGv_i64 cond2 = tcg_temp_new_i64(); 142542659e04SNiccolò Izzo TCGv_i64 cond3 = tcg_temp_new_i64(); 142642659e04SNiccolò Izzo TCGv_i64 mask = tcg_constant_i64(0x8000000000000000ULL); 142742659e04SNiccolò Izzo TCGv_i64 max_pos = tcg_constant_i64(0x7FFFFFFFFFFFFFFFLL); 142842659e04SNiccolò Izzo TCGv_i64 max_neg = tcg_constant_i64(0x8000000000000000LL); 142942659e04SNiccolò Izzo TCGv_i64 zero = tcg_constant_i64(0); 143042659e04SNiccolò Izzo TCGLabel *no_ovfl_label = gen_new_label(); 143142659e04SNiccolò Izzo TCGLabel *ovfl_label = gen_new_label(); 143242659e04SNiccolò Izzo TCGLabel *ret_label = gen_new_label(); 143342659e04SNiccolò Izzo 143442659e04SNiccolò Izzo tcg_gen_add_i64(sum, a, b); 143542659e04SNiccolò Izzo tcg_gen_xor_i64(xor, a, b); 143642659e04SNiccolò Izzo 143742659e04SNiccolò Izzo /* if (xor & mask) */ 143842659e04SNiccolò Izzo tcg_gen_and_i64(cond1, xor, mask); 143942659e04SNiccolò Izzo tcg_gen_brcondi_i64(TCG_COND_NE, cond1, 0, no_ovfl_label); 144042659e04SNiccolò Izzo 144142659e04SNiccolò Izzo /* else if ((a ^ sum) & mask) */ 144242659e04SNiccolò Izzo tcg_gen_xor_i64(cond2, a, sum); 144342659e04SNiccolò Izzo tcg_gen_and_i64(cond2, cond2, mask); 144442659e04SNiccolò Izzo tcg_gen_brcondi_i64(TCG_COND_NE, cond2, 0, ovfl_label); 144542659e04SNiccolò Izzo /* fallthrough to no_ovfl_label branch */ 144642659e04SNiccolò Izzo 144742659e04SNiccolò Izzo /* if branch */ 144842659e04SNiccolò Izzo gen_set_label(no_ovfl_label); 144942659e04SNiccolò Izzo tcg_gen_mov_i64(ret, sum); 145042659e04SNiccolò Izzo tcg_gen_br(ret_label); 145142659e04SNiccolò Izzo 145242659e04SNiccolò Izzo /* else if branch */ 145342659e04SNiccolò Izzo gen_set_label(ovfl_label); 145442659e04SNiccolò Izzo tcg_gen_and_i64(cond3, sum, mask); 145542659e04SNiccolò Izzo tcg_gen_movcond_i64(TCG_COND_NE, ret, cond3, zero, max_pos, max_neg); 1456148ef7fdSTaylor Simpson gen_set_usr_fieldi(ctx, USR_OVF, 1); 145742659e04SNiccolò Izzo 145842659e04SNiccolò Izzo gen_set_label(ret_label); 145942659e04SNiccolò Izzo } 146042659e04SNiccolò Izzo 146157acfcdeSTaylor Simpson #include "tcg_funcs_generated.c.inc" 146257acfcdeSTaylor Simpson #include "tcg_func_table_generated.c.inc" 1463