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