1 /* 2 * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "qemu/osdep.h" 19 #include "cpu.h" 20 #include "internal.h" 21 #include "tcg/tcg-op.h" 22 #include "insn.h" 23 #include "opcodes.h" 24 #include "translate.h" 25 #define QEMU_GENERATE /* Used internally by macros.h */ 26 #include "macros.h" 27 #undef QEMU_GENERATE 28 #include "gen_tcg.h" 29 30 static inline TCGv gen_read_preg(TCGv pred, uint8_t num) 31 { 32 tcg_gen_mov_tl(pred, hex_pred[num]); 33 return pred; 34 } 35 36 static inline void gen_log_predicated_reg_write(int rnum, TCGv val, int slot) 37 { 38 TCGv zero = tcg_const_tl(0); 39 TCGv slot_mask = tcg_temp_new(); 40 41 tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot); 42 tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero, 43 val, hex_new_value[rnum]); 44 if (HEX_DEBUG) { 45 /* 46 * Do this so HELPER(debug_commit_end) will know 47 * 48 * Note that slot_mask indicates the value is not written 49 * (i.e., slot was cancelled), so we create a true/false value before 50 * or'ing with hex_reg_written[rnum]. 51 */ 52 tcg_gen_setcond_tl(TCG_COND_EQ, slot_mask, slot_mask, zero); 53 tcg_gen_or_tl(hex_reg_written[rnum], hex_reg_written[rnum], slot_mask); 54 } 55 56 tcg_temp_free(zero); 57 tcg_temp_free(slot_mask); 58 } 59 60 static inline void gen_log_reg_write(int rnum, TCGv val) 61 { 62 tcg_gen_mov_tl(hex_new_value[rnum], val); 63 if (HEX_DEBUG) { 64 /* Do this so HELPER(debug_commit_end) will know */ 65 tcg_gen_movi_tl(hex_reg_written[rnum], 1); 66 } 67 } 68 69 static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val, int slot) 70 { 71 TCGv val32 = tcg_temp_new(); 72 TCGv zero = tcg_const_tl(0); 73 TCGv slot_mask = tcg_temp_new(); 74 75 tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot); 76 /* Low word */ 77 tcg_gen_extrl_i64_i32(val32, val); 78 tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], 79 slot_mask, zero, 80 val32, hex_new_value[rnum]); 81 /* High word */ 82 tcg_gen_extrh_i64_i32(val32, val); 83 tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum + 1], 84 slot_mask, zero, 85 val32, hex_new_value[rnum + 1]); 86 if (HEX_DEBUG) { 87 /* 88 * Do this so HELPER(debug_commit_end) will know 89 * 90 * Note that slot_mask indicates the value is not written 91 * (i.e., slot was cancelled), so we create a true/false value before 92 * or'ing with hex_reg_written[rnum]. 93 */ 94 tcg_gen_setcond_tl(TCG_COND_EQ, slot_mask, slot_mask, zero); 95 tcg_gen_or_tl(hex_reg_written[rnum], hex_reg_written[rnum], slot_mask); 96 tcg_gen_or_tl(hex_reg_written[rnum + 1], hex_reg_written[rnum + 1], 97 slot_mask); 98 } 99 100 tcg_temp_free(val32); 101 tcg_temp_free(zero); 102 tcg_temp_free(slot_mask); 103 } 104 105 static void gen_log_reg_write_pair(int rnum, TCGv_i64 val) 106 { 107 /* Low word */ 108 tcg_gen_extrl_i64_i32(hex_new_value[rnum], val); 109 if (HEX_DEBUG) { 110 /* Do this so HELPER(debug_commit_end) will know */ 111 tcg_gen_movi_tl(hex_reg_written[rnum], 1); 112 } 113 114 /* High word */ 115 tcg_gen_extrh_i64_i32(hex_new_value[rnum + 1], val); 116 if (HEX_DEBUG) { 117 /* Do this so HELPER(debug_commit_end) will know */ 118 tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1); 119 } 120 } 121 122 static inline void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val) 123 { 124 TCGv zero = tcg_const_tl(0); 125 TCGv base_val = tcg_temp_new(); 126 TCGv and_val = tcg_temp_new(); 127 TCGv pred_written = tcg_temp_new(); 128 129 tcg_gen_andi_tl(base_val, val, 0xff); 130 131 /* 132 * Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual 133 * 134 * Multiple writes to the same preg are and'ed together 135 * If this is the first predicate write in the packet, do a 136 * straight assignment. Otherwise, do an and. 137 */ 138 if (!test_bit(pnum, ctx->pregs_written)) { 139 tcg_gen_mov_tl(hex_new_pred_value[pnum], base_val); 140 } else { 141 tcg_gen_and_tl(hex_new_pred_value[pnum], 142 hex_new_pred_value[pnum], base_val); 143 } 144 tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum); 145 146 tcg_temp_free(zero); 147 tcg_temp_free(base_val); 148 tcg_temp_free(and_val); 149 tcg_temp_free(pred_written); 150 } 151 152 static inline void gen_read_p3_0(TCGv control_reg) 153 { 154 tcg_gen_movi_tl(control_reg, 0); 155 for (int i = 0; i < NUM_PREGS; i++) { 156 tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8); 157 } 158 } 159 160 /* 161 * Certain control registers require special handling on read 162 * HEX_REG_P3_0 aliased to the predicate registers 163 * -> concat the 4 predicate registers together 164 * HEX_REG_PC actual value stored in DisasContext 165 * -> assign from ctx->base.pc_next 166 * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext 167 * -> add current TB changes to existing reg value 168 */ 169 static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num, 170 TCGv dest) 171 { 172 if (reg_num == HEX_REG_P3_0) { 173 gen_read_p3_0(dest); 174 } else if (reg_num == HEX_REG_PC) { 175 tcg_gen_movi_tl(dest, ctx->base.pc_next); 176 } else if (reg_num == HEX_REG_QEMU_PKT_CNT) { 177 tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT], 178 ctx->num_packets); 179 } else if (reg_num == HEX_REG_QEMU_INSN_CNT) { 180 tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT], 181 ctx->num_insns); 182 } else { 183 tcg_gen_mov_tl(dest, hex_gpr[reg_num]); 184 } 185 } 186 187 static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num, 188 TCGv_i64 dest) 189 { 190 if (reg_num == HEX_REG_P3_0) { 191 TCGv p3_0 = tcg_temp_new(); 192 gen_read_p3_0(p3_0); 193 tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]); 194 tcg_temp_free(p3_0); 195 } else if (reg_num == HEX_REG_PC - 1) { 196 TCGv pc = tcg_const_tl(ctx->base.pc_next); 197 tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc); 198 tcg_temp_free(pc); 199 } else if (reg_num == HEX_REG_QEMU_PKT_CNT) { 200 TCGv pkt_cnt = tcg_temp_new(); 201 TCGv insn_cnt = tcg_temp_new(); 202 tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT], 203 ctx->num_packets); 204 tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT], 205 ctx->num_insns); 206 tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt); 207 tcg_temp_free(pkt_cnt); 208 tcg_temp_free(insn_cnt); 209 } else { 210 tcg_gen_concat_i32_i64(dest, 211 hex_gpr[reg_num], 212 hex_gpr[reg_num + 1]); 213 } 214 } 215 216 static inline void gen_write_p3_0(TCGv control_reg) 217 { 218 for (int i = 0; i < NUM_PREGS; i++) { 219 tcg_gen_extract_tl(hex_pred[i], control_reg, i * 8, 8); 220 } 221 } 222 223 /* 224 * Certain control registers require special handling on write 225 * HEX_REG_P3_0 aliased to the predicate registers 226 * -> break the value across 4 predicate registers 227 * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext 228 * -> clear the changes 229 */ 230 static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num, 231 TCGv val) 232 { 233 if (reg_num == HEX_REG_P3_0) { 234 gen_write_p3_0(val); 235 } else { 236 gen_log_reg_write(reg_num, val); 237 ctx_log_reg_write(ctx, reg_num); 238 if (reg_num == HEX_REG_QEMU_PKT_CNT) { 239 ctx->num_packets = 0; 240 } 241 if (reg_num == HEX_REG_QEMU_INSN_CNT) { 242 ctx->num_insns = 0; 243 } 244 } 245 } 246 247 static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num, 248 TCGv_i64 val) 249 { 250 if (reg_num == HEX_REG_P3_0) { 251 TCGv val32 = tcg_temp_new(); 252 tcg_gen_extrl_i64_i32(val32, val); 253 gen_write_p3_0(val32); 254 tcg_gen_extrh_i64_i32(val32, val); 255 gen_log_reg_write(reg_num + 1, val32); 256 tcg_temp_free(val32); 257 ctx_log_reg_write(ctx, reg_num + 1); 258 } else { 259 gen_log_reg_write_pair(reg_num, val); 260 ctx_log_reg_write_pair(ctx, reg_num); 261 if (reg_num == HEX_REG_QEMU_PKT_CNT) { 262 ctx->num_packets = 0; 263 ctx->num_insns = 0; 264 } 265 } 266 } 267 268 static TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign) 269 { 270 if (sign) { 271 tcg_gen_sextract_tl(result, src, N * 8, 8); 272 } else { 273 tcg_gen_extract_tl(result, src, N * 8, 8); 274 } 275 return result; 276 } 277 278 static TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign) 279 { 280 TCGv_i64 res64 = tcg_temp_new_i64(); 281 if (sign) { 282 tcg_gen_sextract_i64(res64, src, N * 8, 8); 283 } else { 284 tcg_gen_extract_i64(res64, src, N * 8, 8); 285 } 286 tcg_gen_extrl_i64_i32(result, res64); 287 tcg_temp_free_i64(res64); 288 289 return result; 290 } 291 292 static inline TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign) 293 { 294 if (sign) { 295 tcg_gen_sextract_tl(result, src, N * 16, 16); 296 } else { 297 tcg_gen_extract_tl(result, src, N * 16, 16); 298 } 299 return result; 300 } 301 302 static inline void gen_set_half(int N, TCGv result, TCGv src) 303 { 304 tcg_gen_deposit_tl(result, result, src, N * 16, 16); 305 } 306 307 static inline void gen_set_half_i64(int N, TCGv_i64 result, TCGv src) 308 { 309 TCGv_i64 src64 = tcg_temp_new_i64(); 310 tcg_gen_extu_i32_i64(src64, src); 311 tcg_gen_deposit_i64(result, result, src64, N * 16, 16); 312 tcg_temp_free_i64(src64); 313 } 314 315 static void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src) 316 { 317 TCGv_i64 src64 = tcg_temp_new_i64(); 318 tcg_gen_extu_i32_i64(src64, src); 319 tcg_gen_deposit_i64(result, result, src64, N * 8, 8); 320 tcg_temp_free_i64(src64); 321 } 322 323 static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index) 324 { 325 tcg_gen_qemu_ld32u(dest, vaddr, mem_index); 326 tcg_gen_mov_tl(hex_llsc_addr, vaddr); 327 tcg_gen_mov_tl(hex_llsc_val, dest); 328 } 329 330 static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index) 331 { 332 tcg_gen_qemu_ld64(dest, vaddr, mem_index); 333 tcg_gen_mov_tl(hex_llsc_addr, vaddr); 334 tcg_gen_mov_i64(hex_llsc_val_i64, dest); 335 } 336 337 static inline void gen_store_conditional4(CPUHexagonState *env, 338 DisasContext *ctx, int prednum, 339 TCGv pred, TCGv vaddr, TCGv src) 340 { 341 TCGLabel *fail = gen_new_label(); 342 TCGLabel *done = gen_new_label(); 343 TCGv one, zero, tmp; 344 345 tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail); 346 347 one = tcg_const_tl(0xff); 348 zero = tcg_const_tl(0); 349 tmp = tcg_temp_new(); 350 tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src, 351 ctx->mem_idx, MO_32); 352 tcg_gen_movcond_tl(TCG_COND_EQ, hex_pred[prednum], tmp, hex_llsc_val, 353 one, zero); 354 tcg_temp_free(one); 355 tcg_temp_free(zero); 356 tcg_temp_free(tmp); 357 tcg_gen_br(done); 358 359 gen_set_label(fail); 360 tcg_gen_movi_tl(pred, 0); 361 362 gen_set_label(done); 363 tcg_gen_movi_tl(hex_llsc_addr, ~0); 364 } 365 366 static inline void gen_store_conditional8(CPUHexagonState *env, 367 DisasContext *ctx, int prednum, 368 TCGv pred, TCGv vaddr, TCGv_i64 src) 369 { 370 TCGLabel *fail = gen_new_label(); 371 TCGLabel *done = gen_new_label(); 372 TCGv_i64 one, zero, tmp; 373 374 tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail); 375 376 one = tcg_const_i64(0xff); 377 zero = tcg_const_i64(0); 378 tmp = tcg_temp_new_i64(); 379 tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src, 380 ctx->mem_idx, MO_64); 381 tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64, 382 one, zero); 383 tcg_gen_extrl_i64_i32(hex_pred[prednum], tmp); 384 tcg_temp_free_i64(one); 385 tcg_temp_free_i64(zero); 386 tcg_temp_free_i64(tmp); 387 tcg_gen_br(done); 388 389 gen_set_label(fail); 390 tcg_gen_movi_tl(pred, 0); 391 392 gen_set_label(done); 393 tcg_gen_movi_tl(hex_llsc_addr, ~0); 394 } 395 396 static inline void gen_store32(TCGv vaddr, TCGv src, int width, int slot) 397 { 398 tcg_gen_mov_tl(hex_store_addr[slot], vaddr); 399 tcg_gen_movi_tl(hex_store_width[slot], width); 400 tcg_gen_mov_tl(hex_store_val32[slot], src); 401 } 402 403 static inline void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, 404 DisasContext *ctx, int slot) 405 { 406 gen_store32(vaddr, src, 1, slot); 407 ctx->store_width[slot] = 1; 408 } 409 410 static inline void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, 411 DisasContext *ctx, int slot) 412 { 413 TCGv tmp = tcg_const_tl(src); 414 gen_store1(cpu_env, vaddr, tmp, ctx, slot); 415 tcg_temp_free(tmp); 416 } 417 418 static inline void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, 419 DisasContext *ctx, int slot) 420 { 421 gen_store32(vaddr, src, 2, slot); 422 ctx->store_width[slot] = 2; 423 } 424 425 static inline void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, 426 DisasContext *ctx, int slot) 427 { 428 TCGv tmp = tcg_const_tl(src); 429 gen_store2(cpu_env, vaddr, tmp, ctx, slot); 430 tcg_temp_free(tmp); 431 } 432 433 static inline void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, 434 DisasContext *ctx, int slot) 435 { 436 gen_store32(vaddr, src, 4, slot); 437 ctx->store_width[slot] = 4; 438 } 439 440 static inline void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, 441 DisasContext *ctx, int slot) 442 { 443 TCGv tmp = tcg_const_tl(src); 444 gen_store4(cpu_env, vaddr, tmp, ctx, slot); 445 tcg_temp_free(tmp); 446 } 447 448 static inline void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, 449 DisasContext *ctx, int slot) 450 { 451 tcg_gen_mov_tl(hex_store_addr[slot], vaddr); 452 tcg_gen_movi_tl(hex_store_width[slot], 8); 453 tcg_gen_mov_i64(hex_store_val64[slot], src); 454 ctx->store_width[slot] = 8; 455 } 456 457 static inline void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, 458 DisasContext *ctx, int slot) 459 { 460 TCGv_i64 tmp = tcg_const_i64(src); 461 gen_store8(cpu_env, vaddr, tmp, ctx, slot); 462 tcg_temp_free_i64(tmp); 463 } 464 465 static TCGv gen_8bitsof(TCGv result, TCGv value) 466 { 467 TCGv zero = tcg_const_tl(0); 468 TCGv ones = tcg_const_tl(0xff); 469 tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero); 470 tcg_temp_free(zero); 471 tcg_temp_free(ones); 472 473 return result; 474 } 475 476 #include "tcg_funcs_generated.c.inc" 477 #include "tcg_func_table_generated.c.inc" 478