1 /* 2 * Tiny Code Generator for QEMU 3 * 4 * Copyright (c) 2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "exec/exec-all.h" 27 #include "tcg/tcg.h" 28 #include "tcg/tcg-op.h" 29 #include "tcg/tcg-mo.h" 30 #include "exec/plugin-gen.h" 31 #include "tcg-internal.h" 32 33 34 void tcg_gen_op1(TCGOpcode opc, TCGArg a1) 35 { 36 TCGOp *op = tcg_emit_op(opc, 1); 37 op->args[0] = a1; 38 } 39 40 void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2) 41 { 42 TCGOp *op = tcg_emit_op(opc, 2); 43 op->args[0] = a1; 44 op->args[1] = a2; 45 } 46 47 void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3) 48 { 49 TCGOp *op = tcg_emit_op(opc, 3); 50 op->args[0] = a1; 51 op->args[1] = a2; 52 op->args[2] = a3; 53 } 54 55 void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4) 56 { 57 TCGOp *op = tcg_emit_op(opc, 4); 58 op->args[0] = a1; 59 op->args[1] = a2; 60 op->args[2] = a3; 61 op->args[3] = a4; 62 } 63 64 void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 65 TCGArg a4, TCGArg a5) 66 { 67 TCGOp *op = tcg_emit_op(opc, 5); 68 op->args[0] = a1; 69 op->args[1] = a2; 70 op->args[2] = a3; 71 op->args[3] = a4; 72 op->args[4] = a5; 73 } 74 75 void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 76 TCGArg a4, TCGArg a5, TCGArg a6) 77 { 78 TCGOp *op = tcg_emit_op(opc, 6); 79 op->args[0] = a1; 80 op->args[1] = a2; 81 op->args[2] = a3; 82 op->args[3] = a4; 83 op->args[4] = a5; 84 op->args[5] = a6; 85 } 86 87 void tcg_gen_mb(TCGBar mb_type) 88 { 89 if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { 90 tcg_gen_op1(INDEX_op_mb, mb_type); 91 } 92 } 93 94 /* 32 bit ops */ 95 96 void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg) 97 { 98 tcg_gen_mov_i32(ret, tcg_constant_i32(arg)); 99 } 100 101 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 102 { 103 /* some cases can be optimized here */ 104 if (arg2 == 0) { 105 tcg_gen_mov_i32(ret, arg1); 106 } else { 107 tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2)); 108 } 109 } 110 111 void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2) 112 { 113 if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) { 114 /* Don't recurse with tcg_gen_neg_i32. */ 115 tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2); 116 } else { 117 tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2); 118 } 119 } 120 121 void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 122 { 123 /* some cases can be optimized here */ 124 if (arg2 == 0) { 125 tcg_gen_mov_i32(ret, arg1); 126 } else { 127 tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2)); 128 } 129 } 130 131 void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 132 { 133 /* Some cases can be optimized here. */ 134 switch (arg2) { 135 case 0: 136 tcg_gen_movi_i32(ret, 0); 137 return; 138 case -1: 139 tcg_gen_mov_i32(ret, arg1); 140 return; 141 case 0xff: 142 /* Don't recurse with tcg_gen_ext8u_i32. */ 143 if (TCG_TARGET_HAS_ext8u_i32) { 144 tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1); 145 return; 146 } 147 break; 148 case 0xffff: 149 if (TCG_TARGET_HAS_ext16u_i32) { 150 tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1); 151 return; 152 } 153 break; 154 } 155 156 tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2)); 157 } 158 159 void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 160 { 161 /* Some cases can be optimized here. */ 162 if (arg2 == -1) { 163 tcg_gen_movi_i32(ret, -1); 164 } else if (arg2 == 0) { 165 tcg_gen_mov_i32(ret, arg1); 166 } else { 167 tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2)); 168 } 169 } 170 171 void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 172 { 173 /* Some cases can be optimized here. */ 174 if (arg2 == 0) { 175 tcg_gen_mov_i32(ret, arg1); 176 } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) { 177 /* Don't recurse with tcg_gen_not_i32. */ 178 tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1); 179 } else { 180 tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2)); 181 } 182 } 183 184 void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 185 { 186 tcg_debug_assert(arg2 >= 0 && arg2 < 32); 187 if (arg2 == 0) { 188 tcg_gen_mov_i32(ret, arg1); 189 } else { 190 tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2)); 191 } 192 } 193 194 void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 195 { 196 tcg_debug_assert(arg2 >= 0 && arg2 < 32); 197 if (arg2 == 0) { 198 tcg_gen_mov_i32(ret, arg1); 199 } else { 200 tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2)); 201 } 202 } 203 204 void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 205 { 206 tcg_debug_assert(arg2 >= 0 && arg2 < 32); 207 if (arg2 == 0) { 208 tcg_gen_mov_i32(ret, arg1); 209 } else { 210 tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2)); 211 } 212 } 213 214 void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l) 215 { 216 if (cond == TCG_COND_ALWAYS) { 217 tcg_gen_br(l); 218 } else if (cond != TCG_COND_NEVER) { 219 l->refs++; 220 tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l)); 221 } 222 } 223 224 void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l) 225 { 226 if (cond == TCG_COND_ALWAYS) { 227 tcg_gen_br(l); 228 } else if (cond != TCG_COND_NEVER) { 229 tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l); 230 } 231 } 232 233 void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret, 234 TCGv_i32 arg1, TCGv_i32 arg2) 235 { 236 if (cond == TCG_COND_ALWAYS) { 237 tcg_gen_movi_i32(ret, 1); 238 } else if (cond == TCG_COND_NEVER) { 239 tcg_gen_movi_i32(ret, 0); 240 } else { 241 tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); 242 } 243 } 244 245 void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, 246 TCGv_i32 arg1, int32_t arg2) 247 { 248 tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2)); 249 } 250 251 void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 252 { 253 if (arg2 == 0) { 254 tcg_gen_movi_i32(ret, 0); 255 } else if (is_power_of_2(arg2)) { 256 tcg_gen_shli_i32(ret, arg1, ctz32(arg2)); 257 } else { 258 tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2)); 259 } 260 } 261 262 void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 263 { 264 if (TCG_TARGET_HAS_div_i32) { 265 tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2); 266 } else if (TCG_TARGET_HAS_div2_i32) { 267 TCGv_i32 t0 = tcg_temp_new_i32(); 268 tcg_gen_sari_i32(t0, arg1, 31); 269 tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2); 270 tcg_temp_free_i32(t0); 271 } else { 272 gen_helper_div_i32(ret, arg1, arg2); 273 } 274 } 275 276 void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 277 { 278 if (TCG_TARGET_HAS_rem_i32) { 279 tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2); 280 } else if (TCG_TARGET_HAS_div_i32) { 281 TCGv_i32 t0 = tcg_temp_new_i32(); 282 tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2); 283 tcg_gen_mul_i32(t0, t0, arg2); 284 tcg_gen_sub_i32(ret, arg1, t0); 285 tcg_temp_free_i32(t0); 286 } else if (TCG_TARGET_HAS_div2_i32) { 287 TCGv_i32 t0 = tcg_temp_new_i32(); 288 tcg_gen_sari_i32(t0, arg1, 31); 289 tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2); 290 tcg_temp_free_i32(t0); 291 } else { 292 gen_helper_rem_i32(ret, arg1, arg2); 293 } 294 } 295 296 void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 297 { 298 if (TCG_TARGET_HAS_div_i32) { 299 tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2); 300 } else if (TCG_TARGET_HAS_div2_i32) { 301 TCGv_i32 t0 = tcg_temp_new_i32(); 302 tcg_gen_movi_i32(t0, 0); 303 tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2); 304 tcg_temp_free_i32(t0); 305 } else { 306 gen_helper_divu_i32(ret, arg1, arg2); 307 } 308 } 309 310 void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 311 { 312 if (TCG_TARGET_HAS_rem_i32) { 313 tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); 314 } else if (TCG_TARGET_HAS_div_i32) { 315 TCGv_i32 t0 = tcg_temp_new_i32(); 316 tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2); 317 tcg_gen_mul_i32(t0, t0, arg2); 318 tcg_gen_sub_i32(ret, arg1, t0); 319 tcg_temp_free_i32(t0); 320 } else if (TCG_TARGET_HAS_div2_i32) { 321 TCGv_i32 t0 = tcg_temp_new_i32(); 322 tcg_gen_movi_i32(t0, 0); 323 tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); 324 tcg_temp_free_i32(t0); 325 } else { 326 gen_helper_remu_i32(ret, arg1, arg2); 327 } 328 } 329 330 void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 331 { 332 if (TCG_TARGET_HAS_andc_i32) { 333 tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2); 334 } else { 335 TCGv_i32 t0 = tcg_temp_new_i32(); 336 tcg_gen_not_i32(t0, arg2); 337 tcg_gen_and_i32(ret, arg1, t0); 338 tcg_temp_free_i32(t0); 339 } 340 } 341 342 void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 343 { 344 if (TCG_TARGET_HAS_eqv_i32) { 345 tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2); 346 } else { 347 tcg_gen_xor_i32(ret, arg1, arg2); 348 tcg_gen_not_i32(ret, ret); 349 } 350 } 351 352 void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 353 { 354 if (TCG_TARGET_HAS_nand_i32) { 355 tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2); 356 } else { 357 tcg_gen_and_i32(ret, arg1, arg2); 358 tcg_gen_not_i32(ret, ret); 359 } 360 } 361 362 void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 363 { 364 if (TCG_TARGET_HAS_nor_i32) { 365 tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2); 366 } else { 367 tcg_gen_or_i32(ret, arg1, arg2); 368 tcg_gen_not_i32(ret, ret); 369 } 370 } 371 372 void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 373 { 374 if (TCG_TARGET_HAS_orc_i32) { 375 tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2); 376 } else { 377 TCGv_i32 t0 = tcg_temp_new_i32(); 378 tcg_gen_not_i32(t0, arg2); 379 tcg_gen_or_i32(ret, arg1, t0); 380 tcg_temp_free_i32(t0); 381 } 382 } 383 384 void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 385 { 386 if (TCG_TARGET_HAS_clz_i32) { 387 tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2); 388 } else if (TCG_TARGET_HAS_clz_i64) { 389 TCGv_i64 t1 = tcg_temp_new_i64(); 390 TCGv_i64 t2 = tcg_temp_new_i64(); 391 tcg_gen_extu_i32_i64(t1, arg1); 392 tcg_gen_extu_i32_i64(t2, arg2); 393 tcg_gen_addi_i64(t2, t2, 32); 394 tcg_gen_clz_i64(t1, t1, t2); 395 tcg_gen_extrl_i64_i32(ret, t1); 396 tcg_temp_free_i64(t1); 397 tcg_temp_free_i64(t2); 398 tcg_gen_subi_i32(ret, ret, 32); 399 } else { 400 gen_helper_clz_i32(ret, arg1, arg2); 401 } 402 } 403 404 void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 405 { 406 tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2)); 407 } 408 409 void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 410 { 411 if (TCG_TARGET_HAS_ctz_i32) { 412 tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2); 413 } else if (TCG_TARGET_HAS_ctz_i64) { 414 TCGv_i64 t1 = tcg_temp_new_i64(); 415 TCGv_i64 t2 = tcg_temp_new_i64(); 416 tcg_gen_extu_i32_i64(t1, arg1); 417 tcg_gen_extu_i32_i64(t2, arg2); 418 tcg_gen_ctz_i64(t1, t1, t2); 419 tcg_gen_extrl_i64_i32(ret, t1); 420 tcg_temp_free_i64(t1); 421 tcg_temp_free_i64(t2); 422 } else if (TCG_TARGET_HAS_ctpop_i32 423 || TCG_TARGET_HAS_ctpop_i64 424 || TCG_TARGET_HAS_clz_i32 425 || TCG_TARGET_HAS_clz_i64) { 426 TCGv_i32 z, t = tcg_temp_new_i32(); 427 428 if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) { 429 tcg_gen_subi_i32(t, arg1, 1); 430 tcg_gen_andc_i32(t, t, arg1); 431 tcg_gen_ctpop_i32(t, t); 432 } else { 433 /* Since all non-x86 hosts have clz(0) == 32, don't fight it. */ 434 tcg_gen_neg_i32(t, arg1); 435 tcg_gen_and_i32(t, t, arg1); 436 tcg_gen_clzi_i32(t, t, 32); 437 tcg_gen_xori_i32(t, t, 31); 438 } 439 z = tcg_constant_i32(0); 440 tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t); 441 tcg_temp_free_i32(t); 442 } else { 443 gen_helper_ctz_i32(ret, arg1, arg2); 444 } 445 } 446 447 void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 448 { 449 if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) { 450 /* This equivalence has the advantage of not requiring a fixup. */ 451 TCGv_i32 t = tcg_temp_new_i32(); 452 tcg_gen_subi_i32(t, arg1, 1); 453 tcg_gen_andc_i32(t, t, arg1); 454 tcg_gen_ctpop_i32(ret, t); 455 tcg_temp_free_i32(t); 456 } else { 457 tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2)); 458 } 459 } 460 461 void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg) 462 { 463 if (TCG_TARGET_HAS_clz_i32) { 464 TCGv_i32 t = tcg_temp_new_i32(); 465 tcg_gen_sari_i32(t, arg, 31); 466 tcg_gen_xor_i32(t, t, arg); 467 tcg_gen_clzi_i32(t, t, 32); 468 tcg_gen_subi_i32(ret, t, 1); 469 tcg_temp_free_i32(t); 470 } else { 471 gen_helper_clrsb_i32(ret, arg); 472 } 473 } 474 475 void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1) 476 { 477 if (TCG_TARGET_HAS_ctpop_i32) { 478 tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1); 479 } else if (TCG_TARGET_HAS_ctpop_i64) { 480 TCGv_i64 t = tcg_temp_new_i64(); 481 tcg_gen_extu_i32_i64(t, arg1); 482 tcg_gen_ctpop_i64(t, t); 483 tcg_gen_extrl_i64_i32(ret, t); 484 tcg_temp_free_i64(t); 485 } else { 486 gen_helper_ctpop_i32(ret, arg1); 487 } 488 } 489 490 void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 491 { 492 if (TCG_TARGET_HAS_rot_i32) { 493 tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2); 494 } else { 495 TCGv_i32 t0, t1; 496 497 t0 = tcg_temp_new_i32(); 498 t1 = tcg_temp_new_i32(); 499 tcg_gen_shl_i32(t0, arg1, arg2); 500 tcg_gen_subfi_i32(t1, 32, arg2); 501 tcg_gen_shr_i32(t1, arg1, t1); 502 tcg_gen_or_i32(ret, t0, t1); 503 tcg_temp_free_i32(t0); 504 tcg_temp_free_i32(t1); 505 } 506 } 507 508 void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 509 { 510 tcg_debug_assert(arg2 >= 0 && arg2 < 32); 511 /* some cases can be optimized here */ 512 if (arg2 == 0) { 513 tcg_gen_mov_i32(ret, arg1); 514 } else if (TCG_TARGET_HAS_rot_i32) { 515 tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2)); 516 } else { 517 TCGv_i32 t0, t1; 518 t0 = tcg_temp_new_i32(); 519 t1 = tcg_temp_new_i32(); 520 tcg_gen_shli_i32(t0, arg1, arg2); 521 tcg_gen_shri_i32(t1, arg1, 32 - arg2); 522 tcg_gen_or_i32(ret, t0, t1); 523 tcg_temp_free_i32(t0); 524 tcg_temp_free_i32(t1); 525 } 526 } 527 528 void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 529 { 530 if (TCG_TARGET_HAS_rot_i32) { 531 tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2); 532 } else { 533 TCGv_i32 t0, t1; 534 535 t0 = tcg_temp_new_i32(); 536 t1 = tcg_temp_new_i32(); 537 tcg_gen_shr_i32(t0, arg1, arg2); 538 tcg_gen_subfi_i32(t1, 32, arg2); 539 tcg_gen_shl_i32(t1, arg1, t1); 540 tcg_gen_or_i32(ret, t0, t1); 541 tcg_temp_free_i32(t0); 542 tcg_temp_free_i32(t1); 543 } 544 } 545 546 void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 547 { 548 tcg_debug_assert(arg2 >= 0 && arg2 < 32); 549 /* some cases can be optimized here */ 550 if (arg2 == 0) { 551 tcg_gen_mov_i32(ret, arg1); 552 } else { 553 tcg_gen_rotli_i32(ret, arg1, 32 - arg2); 554 } 555 } 556 557 void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, 558 unsigned int ofs, unsigned int len) 559 { 560 uint32_t mask; 561 TCGv_i32 t1; 562 563 tcg_debug_assert(ofs < 32); 564 tcg_debug_assert(len > 0); 565 tcg_debug_assert(len <= 32); 566 tcg_debug_assert(ofs + len <= 32); 567 568 if (len == 32) { 569 tcg_gen_mov_i32(ret, arg2); 570 return; 571 } 572 if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) { 573 tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); 574 return; 575 } 576 577 t1 = tcg_temp_new_i32(); 578 579 if (TCG_TARGET_HAS_extract2_i32) { 580 if (ofs + len == 32) { 581 tcg_gen_shli_i32(t1, arg1, len); 582 tcg_gen_extract2_i32(ret, t1, arg2, len); 583 goto done; 584 } 585 if (ofs == 0) { 586 tcg_gen_extract2_i32(ret, arg1, arg2, len); 587 tcg_gen_rotli_i32(ret, ret, len); 588 goto done; 589 } 590 } 591 592 mask = (1u << len) - 1; 593 if (ofs + len < 32) { 594 tcg_gen_andi_i32(t1, arg2, mask); 595 tcg_gen_shli_i32(t1, t1, ofs); 596 } else { 597 tcg_gen_shli_i32(t1, arg2, ofs); 598 } 599 tcg_gen_andi_i32(ret, arg1, ~(mask << ofs)); 600 tcg_gen_or_i32(ret, ret, t1); 601 done: 602 tcg_temp_free_i32(t1); 603 } 604 605 void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, 606 unsigned int ofs, unsigned int len) 607 { 608 tcg_debug_assert(ofs < 32); 609 tcg_debug_assert(len > 0); 610 tcg_debug_assert(len <= 32); 611 tcg_debug_assert(ofs + len <= 32); 612 613 if (ofs + len == 32) { 614 tcg_gen_shli_i32(ret, arg, ofs); 615 } else if (ofs == 0) { 616 tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 617 } else if (TCG_TARGET_HAS_deposit_i32 618 && TCG_TARGET_deposit_i32_valid(ofs, len)) { 619 TCGv_i32 zero = tcg_constant_i32(0); 620 tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); 621 } else { 622 /* To help two-operand hosts we prefer to zero-extend first, 623 which allows ARG to stay live. */ 624 switch (len) { 625 case 16: 626 if (TCG_TARGET_HAS_ext16u_i32) { 627 tcg_gen_ext16u_i32(ret, arg); 628 tcg_gen_shli_i32(ret, ret, ofs); 629 return; 630 } 631 break; 632 case 8: 633 if (TCG_TARGET_HAS_ext8u_i32) { 634 tcg_gen_ext8u_i32(ret, arg); 635 tcg_gen_shli_i32(ret, ret, ofs); 636 return; 637 } 638 break; 639 } 640 /* Otherwise prefer zero-extension over AND for code size. */ 641 switch (ofs + len) { 642 case 16: 643 if (TCG_TARGET_HAS_ext16u_i32) { 644 tcg_gen_shli_i32(ret, arg, ofs); 645 tcg_gen_ext16u_i32(ret, ret); 646 return; 647 } 648 break; 649 case 8: 650 if (TCG_TARGET_HAS_ext8u_i32) { 651 tcg_gen_shli_i32(ret, arg, ofs); 652 tcg_gen_ext8u_i32(ret, ret); 653 return; 654 } 655 break; 656 } 657 tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 658 tcg_gen_shli_i32(ret, ret, ofs); 659 } 660 } 661 662 void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, 663 unsigned int ofs, unsigned int len) 664 { 665 tcg_debug_assert(ofs < 32); 666 tcg_debug_assert(len > 0); 667 tcg_debug_assert(len <= 32); 668 tcg_debug_assert(ofs + len <= 32); 669 670 /* Canonicalize certain special cases, even if extract is supported. */ 671 if (ofs + len == 32) { 672 tcg_gen_shri_i32(ret, arg, 32 - len); 673 return; 674 } 675 if (ofs == 0) { 676 tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 677 return; 678 } 679 680 if (TCG_TARGET_HAS_extract_i32 681 && TCG_TARGET_extract_i32_valid(ofs, len)) { 682 tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len); 683 return; 684 } 685 686 /* Assume that zero-extension, if available, is cheaper than a shift. */ 687 switch (ofs + len) { 688 case 16: 689 if (TCG_TARGET_HAS_ext16u_i32) { 690 tcg_gen_ext16u_i32(ret, arg); 691 tcg_gen_shri_i32(ret, ret, ofs); 692 return; 693 } 694 break; 695 case 8: 696 if (TCG_TARGET_HAS_ext8u_i32) { 697 tcg_gen_ext8u_i32(ret, arg); 698 tcg_gen_shri_i32(ret, ret, ofs); 699 return; 700 } 701 break; 702 } 703 704 /* ??? Ideally we'd know what values are available for immediate AND. 705 Assume that 8 bits are available, plus the special case of 16, 706 so that we get ext8u, ext16u. */ 707 switch (len) { 708 case 1 ... 8: case 16: 709 tcg_gen_shri_i32(ret, arg, ofs); 710 tcg_gen_andi_i32(ret, ret, (1u << len) - 1); 711 break; 712 default: 713 tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 714 tcg_gen_shri_i32(ret, ret, 32 - len); 715 break; 716 } 717 } 718 719 void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg, 720 unsigned int ofs, unsigned int len) 721 { 722 tcg_debug_assert(ofs < 32); 723 tcg_debug_assert(len > 0); 724 tcg_debug_assert(len <= 32); 725 tcg_debug_assert(ofs + len <= 32); 726 727 /* Canonicalize certain special cases, even if extract is supported. */ 728 if (ofs + len == 32) { 729 tcg_gen_sari_i32(ret, arg, 32 - len); 730 return; 731 } 732 if (ofs == 0) { 733 switch (len) { 734 case 16: 735 tcg_gen_ext16s_i32(ret, arg); 736 return; 737 case 8: 738 tcg_gen_ext8s_i32(ret, arg); 739 return; 740 } 741 } 742 743 if (TCG_TARGET_HAS_sextract_i32 744 && TCG_TARGET_extract_i32_valid(ofs, len)) { 745 tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); 746 return; 747 } 748 749 /* Assume that sign-extension, if available, is cheaper than a shift. */ 750 switch (ofs + len) { 751 case 16: 752 if (TCG_TARGET_HAS_ext16s_i32) { 753 tcg_gen_ext16s_i32(ret, arg); 754 tcg_gen_sari_i32(ret, ret, ofs); 755 return; 756 } 757 break; 758 case 8: 759 if (TCG_TARGET_HAS_ext8s_i32) { 760 tcg_gen_ext8s_i32(ret, arg); 761 tcg_gen_sari_i32(ret, ret, ofs); 762 return; 763 } 764 break; 765 } 766 switch (len) { 767 case 16: 768 if (TCG_TARGET_HAS_ext16s_i32) { 769 tcg_gen_shri_i32(ret, arg, ofs); 770 tcg_gen_ext16s_i32(ret, ret); 771 return; 772 } 773 break; 774 case 8: 775 if (TCG_TARGET_HAS_ext8s_i32) { 776 tcg_gen_shri_i32(ret, arg, ofs); 777 tcg_gen_ext8s_i32(ret, ret); 778 return; 779 } 780 break; 781 } 782 783 tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 784 tcg_gen_sari_i32(ret, ret, 32 - len); 785 } 786 787 /* 788 * Extract 32-bits from a 64-bit input, ah:al, starting from ofs. 789 * Unlike tcg_gen_extract_i32 above, len is fixed at 32. 790 */ 791 void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah, 792 unsigned int ofs) 793 { 794 tcg_debug_assert(ofs <= 32); 795 if (ofs == 0) { 796 tcg_gen_mov_i32(ret, al); 797 } else if (ofs == 32) { 798 tcg_gen_mov_i32(ret, ah); 799 } else if (al == ah) { 800 tcg_gen_rotri_i32(ret, al, ofs); 801 } else if (TCG_TARGET_HAS_extract2_i32) { 802 tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs); 803 } else { 804 TCGv_i32 t0 = tcg_temp_new_i32(); 805 tcg_gen_shri_i32(t0, al, ofs); 806 tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs); 807 tcg_temp_free_i32(t0); 808 } 809 } 810 811 void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, 812 TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) 813 { 814 if (cond == TCG_COND_ALWAYS) { 815 tcg_gen_mov_i32(ret, v1); 816 } else if (cond == TCG_COND_NEVER) { 817 tcg_gen_mov_i32(ret, v2); 818 } else if (TCG_TARGET_HAS_movcond_i32) { 819 tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond); 820 } else { 821 TCGv_i32 t0 = tcg_temp_new_i32(); 822 TCGv_i32 t1 = tcg_temp_new_i32(); 823 tcg_gen_setcond_i32(cond, t0, c1, c2); 824 tcg_gen_neg_i32(t0, t0); 825 tcg_gen_and_i32(t1, v1, t0); 826 tcg_gen_andc_i32(ret, v2, t0); 827 tcg_gen_or_i32(ret, ret, t1); 828 tcg_temp_free_i32(t0); 829 tcg_temp_free_i32(t1); 830 } 831 } 832 833 void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 834 TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 835 { 836 if (TCG_TARGET_HAS_add2_i32) { 837 tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh); 838 } else { 839 TCGv_i64 t0 = tcg_temp_new_i64(); 840 TCGv_i64 t1 = tcg_temp_new_i64(); 841 tcg_gen_concat_i32_i64(t0, al, ah); 842 tcg_gen_concat_i32_i64(t1, bl, bh); 843 tcg_gen_add_i64(t0, t0, t1); 844 tcg_gen_extr_i64_i32(rl, rh, t0); 845 tcg_temp_free_i64(t0); 846 tcg_temp_free_i64(t1); 847 } 848 } 849 850 void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 851 TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 852 { 853 if (TCG_TARGET_HAS_sub2_i32) { 854 tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh); 855 } else { 856 TCGv_i64 t0 = tcg_temp_new_i64(); 857 TCGv_i64 t1 = tcg_temp_new_i64(); 858 tcg_gen_concat_i32_i64(t0, al, ah); 859 tcg_gen_concat_i32_i64(t1, bl, bh); 860 tcg_gen_sub_i64(t0, t0, t1); 861 tcg_gen_extr_i64_i32(rl, rh, t0); 862 tcg_temp_free_i64(t0); 863 tcg_temp_free_i64(t1); 864 } 865 } 866 867 void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 868 { 869 if (TCG_TARGET_HAS_mulu2_i32) { 870 tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); 871 } else if (TCG_TARGET_HAS_muluh_i32) { 872 TCGv_i32 t = tcg_temp_new_i32(); 873 tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 874 tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2); 875 tcg_gen_mov_i32(rl, t); 876 tcg_temp_free_i32(t); 877 } else if (TCG_TARGET_REG_BITS == 64) { 878 TCGv_i64 t0 = tcg_temp_new_i64(); 879 TCGv_i64 t1 = tcg_temp_new_i64(); 880 tcg_gen_extu_i32_i64(t0, arg1); 881 tcg_gen_extu_i32_i64(t1, arg2); 882 tcg_gen_mul_i64(t0, t0, t1); 883 tcg_gen_extr_i64_i32(rl, rh, t0); 884 tcg_temp_free_i64(t0); 885 tcg_temp_free_i64(t1); 886 } else { 887 qemu_build_not_reached(); 888 } 889 } 890 891 void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 892 { 893 if (TCG_TARGET_HAS_muls2_i32) { 894 tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); 895 } else if (TCG_TARGET_HAS_mulsh_i32) { 896 TCGv_i32 t = tcg_temp_new_i32(); 897 tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 898 tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2); 899 tcg_gen_mov_i32(rl, t); 900 tcg_temp_free_i32(t); 901 } else if (TCG_TARGET_REG_BITS == 32) { 902 TCGv_i32 t0 = tcg_temp_new_i32(); 903 TCGv_i32 t1 = tcg_temp_new_i32(); 904 TCGv_i32 t2 = tcg_temp_new_i32(); 905 TCGv_i32 t3 = tcg_temp_new_i32(); 906 tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 907 /* Adjust for negative inputs. */ 908 tcg_gen_sari_i32(t2, arg1, 31); 909 tcg_gen_sari_i32(t3, arg2, 31); 910 tcg_gen_and_i32(t2, t2, arg2); 911 tcg_gen_and_i32(t3, t3, arg1); 912 tcg_gen_sub_i32(rh, t1, t2); 913 tcg_gen_sub_i32(rh, rh, t3); 914 tcg_gen_mov_i32(rl, t0); 915 tcg_temp_free_i32(t0); 916 tcg_temp_free_i32(t1); 917 tcg_temp_free_i32(t2); 918 tcg_temp_free_i32(t3); 919 } else { 920 TCGv_i64 t0 = tcg_temp_new_i64(); 921 TCGv_i64 t1 = tcg_temp_new_i64(); 922 tcg_gen_ext_i32_i64(t0, arg1); 923 tcg_gen_ext_i32_i64(t1, arg2); 924 tcg_gen_mul_i64(t0, t0, t1); 925 tcg_gen_extr_i64_i32(rl, rh, t0); 926 tcg_temp_free_i64(t0); 927 tcg_temp_free_i64(t1); 928 } 929 } 930 931 void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 932 { 933 if (TCG_TARGET_REG_BITS == 32) { 934 TCGv_i32 t0 = tcg_temp_new_i32(); 935 TCGv_i32 t1 = tcg_temp_new_i32(); 936 TCGv_i32 t2 = tcg_temp_new_i32(); 937 tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 938 /* Adjust for negative input for the signed arg1. */ 939 tcg_gen_sari_i32(t2, arg1, 31); 940 tcg_gen_and_i32(t2, t2, arg2); 941 tcg_gen_sub_i32(rh, t1, t2); 942 tcg_gen_mov_i32(rl, t0); 943 tcg_temp_free_i32(t0); 944 tcg_temp_free_i32(t1); 945 tcg_temp_free_i32(t2); 946 } else { 947 TCGv_i64 t0 = tcg_temp_new_i64(); 948 TCGv_i64 t1 = tcg_temp_new_i64(); 949 tcg_gen_ext_i32_i64(t0, arg1); 950 tcg_gen_extu_i32_i64(t1, arg2); 951 tcg_gen_mul_i64(t0, t0, t1); 952 tcg_gen_extr_i64_i32(rl, rh, t0); 953 tcg_temp_free_i64(t0); 954 tcg_temp_free_i64(t1); 955 } 956 } 957 958 void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg) 959 { 960 if (TCG_TARGET_HAS_ext8s_i32) { 961 tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg); 962 } else { 963 tcg_gen_shli_i32(ret, arg, 24); 964 tcg_gen_sari_i32(ret, ret, 24); 965 } 966 } 967 968 void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg) 969 { 970 if (TCG_TARGET_HAS_ext16s_i32) { 971 tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg); 972 } else { 973 tcg_gen_shli_i32(ret, arg, 16); 974 tcg_gen_sari_i32(ret, ret, 16); 975 } 976 } 977 978 void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg) 979 { 980 if (TCG_TARGET_HAS_ext8u_i32) { 981 tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg); 982 } else { 983 tcg_gen_andi_i32(ret, arg, 0xffu); 984 } 985 } 986 987 void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg) 988 { 989 if (TCG_TARGET_HAS_ext16u_i32) { 990 tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg); 991 } else { 992 tcg_gen_andi_i32(ret, arg, 0xffffu); 993 } 994 } 995 996 void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags) 997 { 998 /* Only one extension flag may be present. */ 999 tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 1000 1001 if (TCG_TARGET_HAS_bswap16_i32) { 1002 tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags); 1003 } else { 1004 TCGv_i32 t0 = tcg_temp_new_i32(); 1005 TCGv_i32 t1 = tcg_temp_new_i32(); 1006 1007 tcg_gen_shri_i32(t0, arg, 8); 1008 if (!(flags & TCG_BSWAP_IZ)) { 1009 tcg_gen_ext8u_i32(t0, t0); 1010 } 1011 1012 if (flags & TCG_BSWAP_OS) { 1013 tcg_gen_shli_i32(t1, arg, 24); 1014 tcg_gen_sari_i32(t1, t1, 16); 1015 } else if (flags & TCG_BSWAP_OZ) { 1016 tcg_gen_ext8u_i32(t1, arg); 1017 tcg_gen_shli_i32(t1, t1, 8); 1018 } else { 1019 tcg_gen_shli_i32(t1, arg, 8); 1020 } 1021 1022 tcg_gen_or_i32(ret, t0, t1); 1023 tcg_temp_free_i32(t0); 1024 tcg_temp_free_i32(t1); 1025 } 1026 } 1027 1028 void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg) 1029 { 1030 if (TCG_TARGET_HAS_bswap32_i32) { 1031 tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0); 1032 } else { 1033 TCGv_i32 t0 = tcg_temp_new_i32(); 1034 TCGv_i32 t1 = tcg_temp_new_i32(); 1035 TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff); 1036 1037 /* arg = abcd */ 1038 tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */ 1039 tcg_gen_and_i32(t1, arg, t2); /* t1 = .b.d */ 1040 tcg_gen_and_i32(t0, t0, t2); /* t0 = .a.c */ 1041 tcg_gen_shli_i32(t1, t1, 8); /* t1 = b.d. */ 1042 tcg_gen_or_i32(ret, t0, t1); /* ret = badc */ 1043 1044 tcg_gen_shri_i32(t0, ret, 16); /* t0 = ..ba */ 1045 tcg_gen_shli_i32(t1, ret, 16); /* t1 = dc.. */ 1046 tcg_gen_or_i32(ret, t0, t1); /* ret = dcba */ 1047 1048 tcg_temp_free_i32(t0); 1049 tcg_temp_free_i32(t1); 1050 } 1051 } 1052 1053 void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg) 1054 { 1055 /* Swapping 2 16-bit elements is a rotate. */ 1056 tcg_gen_rotli_i32(ret, arg, 16); 1057 } 1058 1059 void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1060 { 1061 tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); 1062 } 1063 1064 void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1065 { 1066 tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); 1067 } 1068 1069 void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1070 { 1071 tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); 1072 } 1073 1074 void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1075 { 1076 tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); 1077 } 1078 1079 void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a) 1080 { 1081 TCGv_i32 t = tcg_temp_new_i32(); 1082 1083 tcg_gen_sari_i32(t, a, 31); 1084 tcg_gen_xor_i32(ret, a, t); 1085 tcg_gen_sub_i32(ret, ret, t); 1086 tcg_temp_free_i32(t); 1087 } 1088 1089 /* 64-bit ops */ 1090 1091 #if TCG_TARGET_REG_BITS == 32 1092 /* These are all inline for TCG_TARGET_REG_BITS == 64. */ 1093 1094 void tcg_gen_discard_i64(TCGv_i64 arg) 1095 { 1096 tcg_gen_discard_i32(TCGV_LOW(arg)); 1097 tcg_gen_discard_i32(TCGV_HIGH(arg)); 1098 } 1099 1100 void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg) 1101 { 1102 TCGTemp *ts = tcgv_i64_temp(arg); 1103 1104 /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */ 1105 if (ts->kind == TEMP_CONST) { 1106 tcg_gen_movi_i64(ret, ts->val); 1107 } else { 1108 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1109 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 1110 } 1111 } 1112 1113 void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 1114 { 1115 tcg_gen_movi_i32(TCGV_LOW(ret), arg); 1116 tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32); 1117 } 1118 1119 void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1120 { 1121 tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset); 1122 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1123 } 1124 1125 void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1126 { 1127 tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset); 1128 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1129 } 1130 1131 void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1132 { 1133 tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset); 1134 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1135 } 1136 1137 void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1138 { 1139 tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset); 1140 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1141 } 1142 1143 void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1144 { 1145 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1146 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1147 } 1148 1149 void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1150 { 1151 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1152 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1153 } 1154 1155 void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1156 { 1157 /* Since arg2 and ret have different types, 1158 they cannot be the same temporary */ 1159 #if HOST_BIG_ENDIAN 1160 tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset); 1161 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4); 1162 #else 1163 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1164 tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4); 1165 #endif 1166 } 1167 1168 void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1169 { 1170 tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset); 1171 } 1172 1173 void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1174 { 1175 tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset); 1176 } 1177 1178 void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1179 { 1180 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1181 } 1182 1183 void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1184 { 1185 #if HOST_BIG_ENDIAN 1186 tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset); 1187 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4); 1188 #else 1189 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1190 tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4); 1191 #endif 1192 } 1193 1194 void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1195 { 1196 tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1197 TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1198 } 1199 1200 void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1201 { 1202 tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1203 TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1204 } 1205 1206 void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1207 { 1208 tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1209 tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1210 } 1211 1212 void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1213 { 1214 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1215 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1216 } 1217 1218 void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1219 { 1220 tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1221 tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1222 } 1223 1224 void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1225 { 1226 gen_helper_shl_i64(ret, arg1, arg2); 1227 } 1228 1229 void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1230 { 1231 gen_helper_shr_i64(ret, arg1, arg2); 1232 } 1233 1234 void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1235 { 1236 gen_helper_sar_i64(ret, arg1, arg2); 1237 } 1238 1239 void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1240 { 1241 TCGv_i64 t0; 1242 TCGv_i32 t1; 1243 1244 t0 = tcg_temp_new_i64(); 1245 t1 = tcg_temp_new_i32(); 1246 1247 tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0), 1248 TCGV_LOW(arg1), TCGV_LOW(arg2)); 1249 1250 tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); 1251 tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1252 tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2)); 1253 tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1254 1255 tcg_gen_mov_i64(ret, t0); 1256 tcg_temp_free_i64(t0); 1257 tcg_temp_free_i32(t1); 1258 } 1259 1260 #else 1261 1262 void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 1263 { 1264 tcg_gen_mov_i64(ret, tcg_constant_i64(arg)); 1265 } 1266 1267 #endif /* TCG_TARGET_REG_SIZE == 32 */ 1268 1269 void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1270 { 1271 /* some cases can be optimized here */ 1272 if (arg2 == 0) { 1273 tcg_gen_mov_i64(ret, arg1); 1274 } else if (TCG_TARGET_REG_BITS == 64) { 1275 tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2)); 1276 } else { 1277 tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 1278 TCGV_LOW(arg1), TCGV_HIGH(arg1), 1279 tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1280 } 1281 } 1282 1283 void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2) 1284 { 1285 if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) { 1286 /* Don't recurse with tcg_gen_neg_i64. */ 1287 tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2); 1288 } else if (TCG_TARGET_REG_BITS == 64) { 1289 tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2); 1290 } else { 1291 tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 1292 tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32), 1293 TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1294 } 1295 } 1296 1297 void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1298 { 1299 /* some cases can be optimized here */ 1300 if (arg2 == 0) { 1301 tcg_gen_mov_i64(ret, arg1); 1302 } else if (TCG_TARGET_REG_BITS == 64) { 1303 tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2)); 1304 } else { 1305 tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 1306 TCGV_LOW(arg1), TCGV_HIGH(arg1), 1307 tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1308 } 1309 } 1310 1311 void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1312 { 1313 if (TCG_TARGET_REG_BITS == 32) { 1314 tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1315 tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 1316 return; 1317 } 1318 1319 /* Some cases can be optimized here. */ 1320 switch (arg2) { 1321 case 0: 1322 tcg_gen_movi_i64(ret, 0); 1323 return; 1324 case -1: 1325 tcg_gen_mov_i64(ret, arg1); 1326 return; 1327 case 0xff: 1328 /* Don't recurse with tcg_gen_ext8u_i64. */ 1329 if (TCG_TARGET_HAS_ext8u_i64) { 1330 tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1); 1331 return; 1332 } 1333 break; 1334 case 0xffff: 1335 if (TCG_TARGET_HAS_ext16u_i64) { 1336 tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1); 1337 return; 1338 } 1339 break; 1340 case 0xffffffffu: 1341 if (TCG_TARGET_HAS_ext32u_i64) { 1342 tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1); 1343 return; 1344 } 1345 break; 1346 } 1347 1348 tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2)); 1349 } 1350 1351 void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1352 { 1353 if (TCG_TARGET_REG_BITS == 32) { 1354 tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1355 tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 1356 return; 1357 } 1358 /* Some cases can be optimized here. */ 1359 if (arg2 == -1) { 1360 tcg_gen_movi_i64(ret, -1); 1361 } else if (arg2 == 0) { 1362 tcg_gen_mov_i64(ret, arg1); 1363 } else { 1364 tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2)); 1365 } 1366 } 1367 1368 void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1369 { 1370 if (TCG_TARGET_REG_BITS == 32) { 1371 tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1372 tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 1373 return; 1374 } 1375 /* Some cases can be optimized here. */ 1376 if (arg2 == 0) { 1377 tcg_gen_mov_i64(ret, arg1); 1378 } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) { 1379 /* Don't recurse with tcg_gen_not_i64. */ 1380 tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1); 1381 } else { 1382 tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2)); 1383 } 1384 } 1385 1386 static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, 1387 unsigned c, bool right, bool arith) 1388 { 1389 tcg_debug_assert(c < 64); 1390 if (c == 0) { 1391 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1392 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1393 } else if (c >= 32) { 1394 c -= 32; 1395 if (right) { 1396 if (arith) { 1397 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1398 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); 1399 } else { 1400 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1401 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1402 } 1403 } else { 1404 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c); 1405 tcg_gen_movi_i32(TCGV_LOW(ret), 0); 1406 } 1407 } else if (right) { 1408 if (TCG_TARGET_HAS_extract2_i32) { 1409 tcg_gen_extract2_i32(TCGV_LOW(ret), 1410 TCGV_LOW(arg1), TCGV_HIGH(arg1), c); 1411 } else { 1412 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 1413 tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret), 1414 TCGV_HIGH(arg1), 32 - c, c); 1415 } 1416 if (arith) { 1417 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 1418 } else { 1419 tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 1420 } 1421 } else { 1422 if (TCG_TARGET_HAS_extract2_i32) { 1423 tcg_gen_extract2_i32(TCGV_HIGH(ret), 1424 TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c); 1425 } else { 1426 TCGv_i32 t0 = tcg_temp_new_i32(); 1427 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c); 1428 tcg_gen_deposit_i32(TCGV_HIGH(ret), t0, 1429 TCGV_HIGH(arg1), c, 32 - c); 1430 tcg_temp_free_i32(t0); 1431 } 1432 tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 1433 } 1434 } 1435 1436 void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1437 { 1438 tcg_debug_assert(arg2 >= 0 && arg2 < 64); 1439 if (TCG_TARGET_REG_BITS == 32) { 1440 tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0); 1441 } else if (arg2 == 0) { 1442 tcg_gen_mov_i64(ret, arg1); 1443 } else { 1444 tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2)); 1445 } 1446 } 1447 1448 void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1449 { 1450 tcg_debug_assert(arg2 >= 0 && arg2 < 64); 1451 if (TCG_TARGET_REG_BITS == 32) { 1452 tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0); 1453 } else if (arg2 == 0) { 1454 tcg_gen_mov_i64(ret, arg1); 1455 } else { 1456 tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2)); 1457 } 1458 } 1459 1460 void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1461 { 1462 tcg_debug_assert(arg2 >= 0 && arg2 < 64); 1463 if (TCG_TARGET_REG_BITS == 32) { 1464 tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1); 1465 } else if (arg2 == 0) { 1466 tcg_gen_mov_i64(ret, arg1); 1467 } else { 1468 tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2)); 1469 } 1470 } 1471 1472 void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l) 1473 { 1474 if (cond == TCG_COND_ALWAYS) { 1475 tcg_gen_br(l); 1476 } else if (cond != TCG_COND_NEVER) { 1477 l->refs++; 1478 if (TCG_TARGET_REG_BITS == 32) { 1479 tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1), 1480 TCGV_HIGH(arg1), TCGV_LOW(arg2), 1481 TCGV_HIGH(arg2), cond, label_arg(l)); 1482 } else { 1483 tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, 1484 label_arg(l)); 1485 } 1486 } 1487 } 1488 1489 void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l) 1490 { 1491 if (TCG_TARGET_REG_BITS == 64) { 1492 tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l); 1493 } else if (cond == TCG_COND_ALWAYS) { 1494 tcg_gen_br(l); 1495 } else if (cond != TCG_COND_NEVER) { 1496 l->refs++; 1497 tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, 1498 TCGV_LOW(arg1), TCGV_HIGH(arg1), 1499 tcg_constant_i32(arg2), 1500 tcg_constant_i32(arg2 >> 32), 1501 cond, label_arg(l)); 1502 } 1503 } 1504 1505 void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, 1506 TCGv_i64 arg1, TCGv_i64 arg2) 1507 { 1508 if (cond == TCG_COND_ALWAYS) { 1509 tcg_gen_movi_i64(ret, 1); 1510 } else if (cond == TCG_COND_NEVER) { 1511 tcg_gen_movi_i64(ret, 0); 1512 } else { 1513 if (TCG_TARGET_REG_BITS == 32) { 1514 tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 1515 TCGV_LOW(arg1), TCGV_HIGH(arg1), 1516 TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 1517 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1518 } else { 1519 tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); 1520 } 1521 } 1522 } 1523 1524 void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, 1525 TCGv_i64 arg1, int64_t arg2) 1526 { 1527 if (TCG_TARGET_REG_BITS == 64) { 1528 tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2)); 1529 } else if (cond == TCG_COND_ALWAYS) { 1530 tcg_gen_movi_i64(ret, 1); 1531 } else if (cond == TCG_COND_NEVER) { 1532 tcg_gen_movi_i64(ret, 0); 1533 } else { 1534 tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 1535 TCGV_LOW(arg1), TCGV_HIGH(arg1), 1536 tcg_constant_i32(arg2), 1537 tcg_constant_i32(arg2 >> 32), cond); 1538 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1539 } 1540 } 1541 1542 void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1543 { 1544 if (arg2 == 0) { 1545 tcg_gen_movi_i64(ret, 0); 1546 } else if (is_power_of_2(arg2)) { 1547 tcg_gen_shli_i64(ret, arg1, ctz64(arg2)); 1548 } else { 1549 TCGv_i64 t0 = tcg_const_i64(arg2); 1550 tcg_gen_mul_i64(ret, arg1, t0); 1551 tcg_temp_free_i64(t0); 1552 } 1553 } 1554 1555 void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1556 { 1557 if (TCG_TARGET_HAS_div_i64) { 1558 tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2); 1559 } else if (TCG_TARGET_HAS_div2_i64) { 1560 TCGv_i64 t0 = tcg_temp_new_i64(); 1561 tcg_gen_sari_i64(t0, arg1, 63); 1562 tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2); 1563 tcg_temp_free_i64(t0); 1564 } else { 1565 gen_helper_div_i64(ret, arg1, arg2); 1566 } 1567 } 1568 1569 void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1570 { 1571 if (TCG_TARGET_HAS_rem_i64) { 1572 tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2); 1573 } else if (TCG_TARGET_HAS_div_i64) { 1574 TCGv_i64 t0 = tcg_temp_new_i64(); 1575 tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2); 1576 tcg_gen_mul_i64(t0, t0, arg2); 1577 tcg_gen_sub_i64(ret, arg1, t0); 1578 tcg_temp_free_i64(t0); 1579 } else if (TCG_TARGET_HAS_div2_i64) { 1580 TCGv_i64 t0 = tcg_temp_new_i64(); 1581 tcg_gen_sari_i64(t0, arg1, 63); 1582 tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2); 1583 tcg_temp_free_i64(t0); 1584 } else { 1585 gen_helper_rem_i64(ret, arg1, arg2); 1586 } 1587 } 1588 1589 void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1590 { 1591 if (TCG_TARGET_HAS_div_i64) { 1592 tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2); 1593 } else if (TCG_TARGET_HAS_div2_i64) { 1594 TCGv_i64 t0 = tcg_temp_new_i64(); 1595 tcg_gen_movi_i64(t0, 0); 1596 tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2); 1597 tcg_temp_free_i64(t0); 1598 } else { 1599 gen_helper_divu_i64(ret, arg1, arg2); 1600 } 1601 } 1602 1603 void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1604 { 1605 if (TCG_TARGET_HAS_rem_i64) { 1606 tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); 1607 } else if (TCG_TARGET_HAS_div_i64) { 1608 TCGv_i64 t0 = tcg_temp_new_i64(); 1609 tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2); 1610 tcg_gen_mul_i64(t0, t0, arg2); 1611 tcg_gen_sub_i64(ret, arg1, t0); 1612 tcg_temp_free_i64(t0); 1613 } else if (TCG_TARGET_HAS_div2_i64) { 1614 TCGv_i64 t0 = tcg_temp_new_i64(); 1615 tcg_gen_movi_i64(t0, 0); 1616 tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); 1617 tcg_temp_free_i64(t0); 1618 } else { 1619 gen_helper_remu_i64(ret, arg1, arg2); 1620 } 1621 } 1622 1623 void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg) 1624 { 1625 if (TCG_TARGET_REG_BITS == 32) { 1626 tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1627 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1628 } else if (TCG_TARGET_HAS_ext8s_i64) { 1629 tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg); 1630 } else { 1631 tcg_gen_shli_i64(ret, arg, 56); 1632 tcg_gen_sari_i64(ret, ret, 56); 1633 } 1634 } 1635 1636 void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg) 1637 { 1638 if (TCG_TARGET_REG_BITS == 32) { 1639 tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1640 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1641 } else if (TCG_TARGET_HAS_ext16s_i64) { 1642 tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg); 1643 } else { 1644 tcg_gen_shli_i64(ret, arg, 48); 1645 tcg_gen_sari_i64(ret, ret, 48); 1646 } 1647 } 1648 1649 void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg) 1650 { 1651 if (TCG_TARGET_REG_BITS == 32) { 1652 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1653 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1654 } else if (TCG_TARGET_HAS_ext32s_i64) { 1655 tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg); 1656 } else { 1657 tcg_gen_shli_i64(ret, arg, 32); 1658 tcg_gen_sari_i64(ret, ret, 32); 1659 } 1660 } 1661 1662 void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg) 1663 { 1664 if (TCG_TARGET_REG_BITS == 32) { 1665 tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1666 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1667 } else if (TCG_TARGET_HAS_ext8u_i64) { 1668 tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg); 1669 } else { 1670 tcg_gen_andi_i64(ret, arg, 0xffu); 1671 } 1672 } 1673 1674 void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg) 1675 { 1676 if (TCG_TARGET_REG_BITS == 32) { 1677 tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1678 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1679 } else if (TCG_TARGET_HAS_ext16u_i64) { 1680 tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg); 1681 } else { 1682 tcg_gen_andi_i64(ret, arg, 0xffffu); 1683 } 1684 } 1685 1686 void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg) 1687 { 1688 if (TCG_TARGET_REG_BITS == 32) { 1689 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1690 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1691 } else if (TCG_TARGET_HAS_ext32u_i64) { 1692 tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg); 1693 } else { 1694 tcg_gen_andi_i64(ret, arg, 0xffffffffu); 1695 } 1696 } 1697 1698 void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 1699 { 1700 /* Only one extension flag may be present. */ 1701 tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 1702 1703 if (TCG_TARGET_REG_BITS == 32) { 1704 tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags); 1705 if (flags & TCG_BSWAP_OS) { 1706 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1707 } else { 1708 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1709 } 1710 } else if (TCG_TARGET_HAS_bswap16_i64) { 1711 tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags); 1712 } else { 1713 TCGv_i64 t0 = tcg_temp_new_i64(); 1714 TCGv_i64 t1 = tcg_temp_new_i64(); 1715 1716 tcg_gen_shri_i64(t0, arg, 8); 1717 if (!(flags & TCG_BSWAP_IZ)) { 1718 tcg_gen_ext8u_i64(t0, t0); 1719 } 1720 1721 if (flags & TCG_BSWAP_OS) { 1722 tcg_gen_shli_i64(t1, arg, 56); 1723 tcg_gen_sari_i64(t1, t1, 48); 1724 } else if (flags & TCG_BSWAP_OZ) { 1725 tcg_gen_ext8u_i64(t1, arg); 1726 tcg_gen_shli_i64(t1, t1, 8); 1727 } else { 1728 tcg_gen_shli_i64(t1, arg, 8); 1729 } 1730 1731 tcg_gen_or_i64(ret, t0, t1); 1732 tcg_temp_free_i64(t0); 1733 tcg_temp_free_i64(t1); 1734 } 1735 } 1736 1737 void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 1738 { 1739 /* Only one extension flag may be present. */ 1740 tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 1741 1742 if (TCG_TARGET_REG_BITS == 32) { 1743 tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1744 if (flags & TCG_BSWAP_OS) { 1745 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1746 } else { 1747 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1748 } 1749 } else if (TCG_TARGET_HAS_bswap32_i64) { 1750 tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags); 1751 } else { 1752 TCGv_i64 t0 = tcg_temp_new_i64(); 1753 TCGv_i64 t1 = tcg_temp_new_i64(); 1754 TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff); 1755 1756 /* arg = xxxxabcd */ 1757 tcg_gen_shri_i64(t0, arg, 8); /* t0 = .xxxxabc */ 1758 tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */ 1759 tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */ 1760 tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */ 1761 tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */ 1762 1763 tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */ 1764 tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */ 1765 if (flags & TCG_BSWAP_OS) { 1766 tcg_gen_sari_i64(t1, t1, 32); /* t1 = ssssdc.. */ 1767 } else { 1768 tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */ 1769 } 1770 tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba */ 1771 1772 tcg_temp_free_i64(t0); 1773 tcg_temp_free_i64(t1); 1774 } 1775 } 1776 1777 void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg) 1778 { 1779 if (TCG_TARGET_REG_BITS == 32) { 1780 TCGv_i32 t0, t1; 1781 t0 = tcg_temp_new_i32(); 1782 t1 = tcg_temp_new_i32(); 1783 1784 tcg_gen_bswap32_i32(t0, TCGV_LOW(arg)); 1785 tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg)); 1786 tcg_gen_mov_i32(TCGV_LOW(ret), t1); 1787 tcg_gen_mov_i32(TCGV_HIGH(ret), t0); 1788 tcg_temp_free_i32(t0); 1789 tcg_temp_free_i32(t1); 1790 } else if (TCG_TARGET_HAS_bswap64_i64) { 1791 tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0); 1792 } else { 1793 TCGv_i64 t0 = tcg_temp_new_i64(); 1794 TCGv_i64 t1 = tcg_temp_new_i64(); 1795 TCGv_i64 t2 = tcg_temp_new_i64(); 1796 1797 /* arg = abcdefgh */ 1798 tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull); 1799 tcg_gen_shri_i64(t0, arg, 8); /* t0 = .abcdefg */ 1800 tcg_gen_and_i64(t1, arg, t2); /* t1 = .b.d.f.h */ 1801 tcg_gen_and_i64(t0, t0, t2); /* t0 = .a.c.e.g */ 1802 tcg_gen_shli_i64(t1, t1, 8); /* t1 = b.d.f.h. */ 1803 tcg_gen_or_i64(ret, t0, t1); /* ret = badcfehg */ 1804 1805 tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull); 1806 tcg_gen_shri_i64(t0, ret, 16); /* t0 = ..badcfe */ 1807 tcg_gen_and_i64(t1, ret, t2); /* t1 = ..dc..hg */ 1808 tcg_gen_and_i64(t0, t0, t2); /* t0 = ..ba..fe */ 1809 tcg_gen_shli_i64(t1, t1, 16); /* t1 = dc..hg.. */ 1810 tcg_gen_or_i64(ret, t0, t1); /* ret = dcbahgfe */ 1811 1812 tcg_gen_shri_i64(t0, ret, 32); /* t0 = ....dcba */ 1813 tcg_gen_shli_i64(t1, ret, 32); /* t1 = hgfe.... */ 1814 tcg_gen_or_i64(ret, t0, t1); /* ret = hgfedcba */ 1815 1816 tcg_temp_free_i64(t0); 1817 tcg_temp_free_i64(t1); 1818 tcg_temp_free_i64(t2); 1819 } 1820 } 1821 1822 void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg) 1823 { 1824 uint64_t m = 0x0000ffff0000ffffull; 1825 TCGv_i64 t0 = tcg_temp_new_i64(); 1826 TCGv_i64 t1 = tcg_temp_new_i64(); 1827 1828 /* See include/qemu/bitops.h, hswap64. */ 1829 tcg_gen_rotli_i64(t1, arg, 32); 1830 tcg_gen_andi_i64(t0, t1, m); 1831 tcg_gen_shli_i64(t0, t0, 16); 1832 tcg_gen_shri_i64(t1, t1, 16); 1833 tcg_gen_andi_i64(t1, t1, m); 1834 tcg_gen_or_i64(ret, t0, t1); 1835 1836 tcg_temp_free_i64(t0); 1837 tcg_temp_free_i64(t1); 1838 } 1839 1840 void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg) 1841 { 1842 /* Swapping 2 32-bit elements is a rotate. */ 1843 tcg_gen_rotli_i64(ret, arg, 32); 1844 } 1845 1846 void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg) 1847 { 1848 if (TCG_TARGET_REG_BITS == 32) { 1849 tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1850 tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 1851 } else if (TCG_TARGET_HAS_not_i64) { 1852 tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg); 1853 } else { 1854 tcg_gen_xori_i64(ret, arg, -1); 1855 } 1856 } 1857 1858 void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1859 { 1860 if (TCG_TARGET_REG_BITS == 32) { 1861 tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1862 tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1863 } else if (TCG_TARGET_HAS_andc_i64) { 1864 tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2); 1865 } else { 1866 TCGv_i64 t0 = tcg_temp_new_i64(); 1867 tcg_gen_not_i64(t0, arg2); 1868 tcg_gen_and_i64(ret, arg1, t0); 1869 tcg_temp_free_i64(t0); 1870 } 1871 } 1872 1873 void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1874 { 1875 if (TCG_TARGET_REG_BITS == 32) { 1876 tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1877 tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1878 } else if (TCG_TARGET_HAS_eqv_i64) { 1879 tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2); 1880 } else { 1881 tcg_gen_xor_i64(ret, arg1, arg2); 1882 tcg_gen_not_i64(ret, ret); 1883 } 1884 } 1885 1886 void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1887 { 1888 if (TCG_TARGET_REG_BITS == 32) { 1889 tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1890 tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1891 } else if (TCG_TARGET_HAS_nand_i64) { 1892 tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2); 1893 } else { 1894 tcg_gen_and_i64(ret, arg1, arg2); 1895 tcg_gen_not_i64(ret, ret); 1896 } 1897 } 1898 1899 void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1900 { 1901 if (TCG_TARGET_REG_BITS == 32) { 1902 tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1903 tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1904 } else if (TCG_TARGET_HAS_nor_i64) { 1905 tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2); 1906 } else { 1907 tcg_gen_or_i64(ret, arg1, arg2); 1908 tcg_gen_not_i64(ret, ret); 1909 } 1910 } 1911 1912 void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1913 { 1914 if (TCG_TARGET_REG_BITS == 32) { 1915 tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1916 tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1917 } else if (TCG_TARGET_HAS_orc_i64) { 1918 tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2); 1919 } else { 1920 TCGv_i64 t0 = tcg_temp_new_i64(); 1921 tcg_gen_not_i64(t0, arg2); 1922 tcg_gen_or_i64(ret, arg1, t0); 1923 tcg_temp_free_i64(t0); 1924 } 1925 } 1926 1927 void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1928 { 1929 if (TCG_TARGET_HAS_clz_i64) { 1930 tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2); 1931 } else { 1932 gen_helper_clz_i64(ret, arg1, arg2); 1933 } 1934 } 1935 1936 void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 1937 { 1938 if (TCG_TARGET_REG_BITS == 32 1939 && TCG_TARGET_HAS_clz_i32 1940 && arg2 <= 0xffffffffu) { 1941 TCGv_i32 t = tcg_temp_new_i32(); 1942 tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32); 1943 tcg_gen_addi_i32(t, t, 32); 1944 tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t); 1945 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1946 tcg_temp_free_i32(t); 1947 } else { 1948 TCGv_i64 t0 = tcg_const_i64(arg2); 1949 tcg_gen_clz_i64(ret, arg1, t0); 1950 tcg_temp_free_i64(t0); 1951 } 1952 } 1953 1954 void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1955 { 1956 if (TCG_TARGET_HAS_ctz_i64) { 1957 tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2); 1958 } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) { 1959 TCGv_i64 z, t = tcg_temp_new_i64(); 1960 1961 if (TCG_TARGET_HAS_ctpop_i64) { 1962 tcg_gen_subi_i64(t, arg1, 1); 1963 tcg_gen_andc_i64(t, t, arg1); 1964 tcg_gen_ctpop_i64(t, t); 1965 } else { 1966 /* Since all non-x86 hosts have clz(0) == 64, don't fight it. */ 1967 tcg_gen_neg_i64(t, arg1); 1968 tcg_gen_and_i64(t, t, arg1); 1969 tcg_gen_clzi_i64(t, t, 64); 1970 tcg_gen_xori_i64(t, t, 63); 1971 } 1972 z = tcg_constant_i64(0); 1973 tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t); 1974 tcg_temp_free_i64(t); 1975 tcg_temp_free_i64(z); 1976 } else { 1977 gen_helper_ctz_i64(ret, arg1, arg2); 1978 } 1979 } 1980 1981 void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 1982 { 1983 if (TCG_TARGET_REG_BITS == 32 1984 && TCG_TARGET_HAS_ctz_i32 1985 && arg2 <= 0xffffffffu) { 1986 TCGv_i32 t32 = tcg_temp_new_i32(); 1987 tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32); 1988 tcg_gen_addi_i32(t32, t32, 32); 1989 tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32); 1990 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1991 tcg_temp_free_i32(t32); 1992 } else if (!TCG_TARGET_HAS_ctz_i64 1993 && TCG_TARGET_HAS_ctpop_i64 1994 && arg2 == 64) { 1995 /* This equivalence has the advantage of not requiring a fixup. */ 1996 TCGv_i64 t = tcg_temp_new_i64(); 1997 tcg_gen_subi_i64(t, arg1, 1); 1998 tcg_gen_andc_i64(t, t, arg1); 1999 tcg_gen_ctpop_i64(ret, t); 2000 tcg_temp_free_i64(t); 2001 } else { 2002 TCGv_i64 t0 = tcg_const_i64(arg2); 2003 tcg_gen_ctz_i64(ret, arg1, t0); 2004 tcg_temp_free_i64(t0); 2005 } 2006 } 2007 2008 void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg) 2009 { 2010 if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) { 2011 TCGv_i64 t = tcg_temp_new_i64(); 2012 tcg_gen_sari_i64(t, arg, 63); 2013 tcg_gen_xor_i64(t, t, arg); 2014 tcg_gen_clzi_i64(t, t, 64); 2015 tcg_gen_subi_i64(ret, t, 1); 2016 tcg_temp_free_i64(t); 2017 } else { 2018 gen_helper_clrsb_i64(ret, arg); 2019 } 2020 } 2021 2022 void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1) 2023 { 2024 if (TCG_TARGET_HAS_ctpop_i64) { 2025 tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1); 2026 } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) { 2027 tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2028 tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2029 tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret)); 2030 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2031 } else { 2032 gen_helper_ctpop_i64(ret, arg1); 2033 } 2034 } 2035 2036 void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2037 { 2038 if (TCG_TARGET_HAS_rot_i64) { 2039 tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2); 2040 } else { 2041 TCGv_i64 t0, t1; 2042 t0 = tcg_temp_new_i64(); 2043 t1 = tcg_temp_new_i64(); 2044 tcg_gen_shl_i64(t0, arg1, arg2); 2045 tcg_gen_subfi_i64(t1, 64, arg2); 2046 tcg_gen_shr_i64(t1, arg1, t1); 2047 tcg_gen_or_i64(ret, t0, t1); 2048 tcg_temp_free_i64(t0); 2049 tcg_temp_free_i64(t1); 2050 } 2051 } 2052 2053 void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2054 { 2055 tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2056 /* some cases can be optimized here */ 2057 if (arg2 == 0) { 2058 tcg_gen_mov_i64(ret, arg1); 2059 } else if (TCG_TARGET_HAS_rot_i64) { 2060 tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2)); 2061 } else { 2062 TCGv_i64 t0, t1; 2063 t0 = tcg_temp_new_i64(); 2064 t1 = tcg_temp_new_i64(); 2065 tcg_gen_shli_i64(t0, arg1, arg2); 2066 tcg_gen_shri_i64(t1, arg1, 64 - arg2); 2067 tcg_gen_or_i64(ret, t0, t1); 2068 tcg_temp_free_i64(t0); 2069 tcg_temp_free_i64(t1); 2070 } 2071 } 2072 2073 void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2074 { 2075 if (TCG_TARGET_HAS_rot_i64) { 2076 tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2); 2077 } else { 2078 TCGv_i64 t0, t1; 2079 t0 = tcg_temp_new_i64(); 2080 t1 = tcg_temp_new_i64(); 2081 tcg_gen_shr_i64(t0, arg1, arg2); 2082 tcg_gen_subfi_i64(t1, 64, arg2); 2083 tcg_gen_shl_i64(t1, arg1, t1); 2084 tcg_gen_or_i64(ret, t0, t1); 2085 tcg_temp_free_i64(t0); 2086 tcg_temp_free_i64(t1); 2087 } 2088 } 2089 2090 void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2091 { 2092 tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2093 /* some cases can be optimized here */ 2094 if (arg2 == 0) { 2095 tcg_gen_mov_i64(ret, arg1); 2096 } else { 2097 tcg_gen_rotli_i64(ret, arg1, 64 - arg2); 2098 } 2099 } 2100 2101 void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, 2102 unsigned int ofs, unsigned int len) 2103 { 2104 uint64_t mask; 2105 TCGv_i64 t1; 2106 2107 tcg_debug_assert(ofs < 64); 2108 tcg_debug_assert(len > 0); 2109 tcg_debug_assert(len <= 64); 2110 tcg_debug_assert(ofs + len <= 64); 2111 2112 if (len == 64) { 2113 tcg_gen_mov_i64(ret, arg2); 2114 return; 2115 } 2116 if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) { 2117 tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); 2118 return; 2119 } 2120 2121 if (TCG_TARGET_REG_BITS == 32) { 2122 if (ofs >= 32) { 2123 tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 2124 TCGV_LOW(arg2), ofs - 32, len); 2125 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2126 return; 2127 } 2128 if (ofs + len <= 32) { 2129 tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1), 2130 TCGV_LOW(arg2), ofs, len); 2131 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2132 return; 2133 } 2134 } 2135 2136 t1 = tcg_temp_new_i64(); 2137 2138 if (TCG_TARGET_HAS_extract2_i64) { 2139 if (ofs + len == 64) { 2140 tcg_gen_shli_i64(t1, arg1, len); 2141 tcg_gen_extract2_i64(ret, t1, arg2, len); 2142 goto done; 2143 } 2144 if (ofs == 0) { 2145 tcg_gen_extract2_i64(ret, arg1, arg2, len); 2146 tcg_gen_rotli_i64(ret, ret, len); 2147 goto done; 2148 } 2149 } 2150 2151 mask = (1ull << len) - 1; 2152 if (ofs + len < 64) { 2153 tcg_gen_andi_i64(t1, arg2, mask); 2154 tcg_gen_shli_i64(t1, t1, ofs); 2155 } else { 2156 tcg_gen_shli_i64(t1, arg2, ofs); 2157 } 2158 tcg_gen_andi_i64(ret, arg1, ~(mask << ofs)); 2159 tcg_gen_or_i64(ret, ret, t1); 2160 done: 2161 tcg_temp_free_i64(t1); 2162 } 2163 2164 void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, 2165 unsigned int ofs, unsigned int len) 2166 { 2167 tcg_debug_assert(ofs < 64); 2168 tcg_debug_assert(len > 0); 2169 tcg_debug_assert(len <= 64); 2170 tcg_debug_assert(ofs + len <= 64); 2171 2172 if (ofs + len == 64) { 2173 tcg_gen_shli_i64(ret, arg, ofs); 2174 } else if (ofs == 0) { 2175 tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 2176 } else if (TCG_TARGET_HAS_deposit_i64 2177 && TCG_TARGET_deposit_i64_valid(ofs, len)) { 2178 TCGv_i64 zero = tcg_constant_i64(0); 2179 tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); 2180 } else { 2181 if (TCG_TARGET_REG_BITS == 32) { 2182 if (ofs >= 32) { 2183 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg), 2184 ofs - 32, len); 2185 tcg_gen_movi_i32(TCGV_LOW(ret), 0); 2186 return; 2187 } 2188 if (ofs + len <= 32) { 2189 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 2190 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2191 return; 2192 } 2193 } 2194 /* To help two-operand hosts we prefer to zero-extend first, 2195 which allows ARG to stay live. */ 2196 switch (len) { 2197 case 32: 2198 if (TCG_TARGET_HAS_ext32u_i64) { 2199 tcg_gen_ext32u_i64(ret, arg); 2200 tcg_gen_shli_i64(ret, ret, ofs); 2201 return; 2202 } 2203 break; 2204 case 16: 2205 if (TCG_TARGET_HAS_ext16u_i64) { 2206 tcg_gen_ext16u_i64(ret, arg); 2207 tcg_gen_shli_i64(ret, ret, ofs); 2208 return; 2209 } 2210 break; 2211 case 8: 2212 if (TCG_TARGET_HAS_ext8u_i64) { 2213 tcg_gen_ext8u_i64(ret, arg); 2214 tcg_gen_shli_i64(ret, ret, ofs); 2215 return; 2216 } 2217 break; 2218 } 2219 /* Otherwise prefer zero-extension over AND for code size. */ 2220 switch (ofs + len) { 2221 case 32: 2222 if (TCG_TARGET_HAS_ext32u_i64) { 2223 tcg_gen_shli_i64(ret, arg, ofs); 2224 tcg_gen_ext32u_i64(ret, ret); 2225 return; 2226 } 2227 break; 2228 case 16: 2229 if (TCG_TARGET_HAS_ext16u_i64) { 2230 tcg_gen_shli_i64(ret, arg, ofs); 2231 tcg_gen_ext16u_i64(ret, ret); 2232 return; 2233 } 2234 break; 2235 case 8: 2236 if (TCG_TARGET_HAS_ext8u_i64) { 2237 tcg_gen_shli_i64(ret, arg, ofs); 2238 tcg_gen_ext8u_i64(ret, ret); 2239 return; 2240 } 2241 break; 2242 } 2243 tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 2244 tcg_gen_shli_i64(ret, ret, ofs); 2245 } 2246 } 2247 2248 void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, 2249 unsigned int ofs, unsigned int len) 2250 { 2251 tcg_debug_assert(ofs < 64); 2252 tcg_debug_assert(len > 0); 2253 tcg_debug_assert(len <= 64); 2254 tcg_debug_assert(ofs + len <= 64); 2255 2256 /* Canonicalize certain special cases, even if extract is supported. */ 2257 if (ofs + len == 64) { 2258 tcg_gen_shri_i64(ret, arg, 64 - len); 2259 return; 2260 } 2261 if (ofs == 0) { 2262 tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 2263 return; 2264 } 2265 2266 if (TCG_TARGET_REG_BITS == 32) { 2267 /* Look for a 32-bit extract within one of the two words. */ 2268 if (ofs >= 32) { 2269 tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 2270 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2271 return; 2272 } 2273 if (ofs + len <= 32) { 2274 tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 2275 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2276 return; 2277 } 2278 /* The field is split across two words. One double-word 2279 shift is better than two double-word shifts. */ 2280 goto do_shift_and; 2281 } 2282 2283 if (TCG_TARGET_HAS_extract_i64 2284 && TCG_TARGET_extract_i64_valid(ofs, len)) { 2285 tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len); 2286 return; 2287 } 2288 2289 /* Assume that zero-extension, if available, is cheaper than a shift. */ 2290 switch (ofs + len) { 2291 case 32: 2292 if (TCG_TARGET_HAS_ext32u_i64) { 2293 tcg_gen_ext32u_i64(ret, arg); 2294 tcg_gen_shri_i64(ret, ret, ofs); 2295 return; 2296 } 2297 break; 2298 case 16: 2299 if (TCG_TARGET_HAS_ext16u_i64) { 2300 tcg_gen_ext16u_i64(ret, arg); 2301 tcg_gen_shri_i64(ret, ret, ofs); 2302 return; 2303 } 2304 break; 2305 case 8: 2306 if (TCG_TARGET_HAS_ext8u_i64) { 2307 tcg_gen_ext8u_i64(ret, arg); 2308 tcg_gen_shri_i64(ret, ret, ofs); 2309 return; 2310 } 2311 break; 2312 } 2313 2314 /* ??? Ideally we'd know what values are available for immediate AND. 2315 Assume that 8 bits are available, plus the special cases of 16 and 32, 2316 so that we get ext8u, ext16u, and ext32u. */ 2317 switch (len) { 2318 case 1 ... 8: case 16: case 32: 2319 do_shift_and: 2320 tcg_gen_shri_i64(ret, arg, ofs); 2321 tcg_gen_andi_i64(ret, ret, (1ull << len) - 1); 2322 break; 2323 default: 2324 tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 2325 tcg_gen_shri_i64(ret, ret, 64 - len); 2326 break; 2327 } 2328 } 2329 2330 void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg, 2331 unsigned int ofs, unsigned int len) 2332 { 2333 tcg_debug_assert(ofs < 64); 2334 tcg_debug_assert(len > 0); 2335 tcg_debug_assert(len <= 64); 2336 tcg_debug_assert(ofs + len <= 64); 2337 2338 /* Canonicalize certain special cases, even if sextract is supported. */ 2339 if (ofs + len == 64) { 2340 tcg_gen_sari_i64(ret, arg, 64 - len); 2341 return; 2342 } 2343 if (ofs == 0) { 2344 switch (len) { 2345 case 32: 2346 tcg_gen_ext32s_i64(ret, arg); 2347 return; 2348 case 16: 2349 tcg_gen_ext16s_i64(ret, arg); 2350 return; 2351 case 8: 2352 tcg_gen_ext8s_i64(ret, arg); 2353 return; 2354 } 2355 } 2356 2357 if (TCG_TARGET_REG_BITS == 32) { 2358 /* Look for a 32-bit extract within one of the two words. */ 2359 if (ofs >= 32) { 2360 tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 2361 } else if (ofs + len <= 32) { 2362 tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 2363 } else if (ofs == 0) { 2364 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2365 tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32); 2366 return; 2367 } else if (len > 32) { 2368 TCGv_i32 t = tcg_temp_new_i32(); 2369 /* Extract the bits for the high word normally. */ 2370 tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32); 2371 /* Shift the field down for the low part. */ 2372 tcg_gen_shri_i64(ret, arg, ofs); 2373 /* Overwrite the shift into the high part. */ 2374 tcg_gen_mov_i32(TCGV_HIGH(ret), t); 2375 tcg_temp_free_i32(t); 2376 return; 2377 } else { 2378 /* Shift the field down for the low part, such that the 2379 field sits at the MSB. */ 2380 tcg_gen_shri_i64(ret, arg, ofs + len - 32); 2381 /* Shift the field down from the MSB, sign extending. */ 2382 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len); 2383 } 2384 /* Sign-extend the field from 32 bits. */ 2385 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 2386 return; 2387 } 2388 2389 if (TCG_TARGET_HAS_sextract_i64 2390 && TCG_TARGET_extract_i64_valid(ofs, len)) { 2391 tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); 2392 return; 2393 } 2394 2395 /* Assume that sign-extension, if available, is cheaper than a shift. */ 2396 switch (ofs + len) { 2397 case 32: 2398 if (TCG_TARGET_HAS_ext32s_i64) { 2399 tcg_gen_ext32s_i64(ret, arg); 2400 tcg_gen_sari_i64(ret, ret, ofs); 2401 return; 2402 } 2403 break; 2404 case 16: 2405 if (TCG_TARGET_HAS_ext16s_i64) { 2406 tcg_gen_ext16s_i64(ret, arg); 2407 tcg_gen_sari_i64(ret, ret, ofs); 2408 return; 2409 } 2410 break; 2411 case 8: 2412 if (TCG_TARGET_HAS_ext8s_i64) { 2413 tcg_gen_ext8s_i64(ret, arg); 2414 tcg_gen_sari_i64(ret, ret, ofs); 2415 return; 2416 } 2417 break; 2418 } 2419 switch (len) { 2420 case 32: 2421 if (TCG_TARGET_HAS_ext32s_i64) { 2422 tcg_gen_shri_i64(ret, arg, ofs); 2423 tcg_gen_ext32s_i64(ret, ret); 2424 return; 2425 } 2426 break; 2427 case 16: 2428 if (TCG_TARGET_HAS_ext16s_i64) { 2429 tcg_gen_shri_i64(ret, arg, ofs); 2430 tcg_gen_ext16s_i64(ret, ret); 2431 return; 2432 } 2433 break; 2434 case 8: 2435 if (TCG_TARGET_HAS_ext8s_i64) { 2436 tcg_gen_shri_i64(ret, arg, ofs); 2437 tcg_gen_ext8s_i64(ret, ret); 2438 return; 2439 } 2440 break; 2441 } 2442 tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 2443 tcg_gen_sari_i64(ret, ret, 64 - len); 2444 } 2445 2446 /* 2447 * Extract 64 bits from a 128-bit input, ah:al, starting from ofs. 2448 * Unlike tcg_gen_extract_i64 above, len is fixed at 64. 2449 */ 2450 void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah, 2451 unsigned int ofs) 2452 { 2453 tcg_debug_assert(ofs <= 64); 2454 if (ofs == 0) { 2455 tcg_gen_mov_i64(ret, al); 2456 } else if (ofs == 64) { 2457 tcg_gen_mov_i64(ret, ah); 2458 } else if (al == ah) { 2459 tcg_gen_rotri_i64(ret, al, ofs); 2460 } else if (TCG_TARGET_HAS_extract2_i64) { 2461 tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs); 2462 } else { 2463 TCGv_i64 t0 = tcg_temp_new_i64(); 2464 tcg_gen_shri_i64(t0, al, ofs); 2465 tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs); 2466 tcg_temp_free_i64(t0); 2467 } 2468 } 2469 2470 void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, 2471 TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2) 2472 { 2473 if (cond == TCG_COND_ALWAYS) { 2474 tcg_gen_mov_i64(ret, v1); 2475 } else if (cond == TCG_COND_NEVER) { 2476 tcg_gen_mov_i64(ret, v2); 2477 } else if (TCG_TARGET_REG_BITS == 32) { 2478 TCGv_i32 t0 = tcg_temp_new_i32(); 2479 TCGv_i32 t1 = tcg_temp_new_i32(); 2480 tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, 2481 TCGV_LOW(c1), TCGV_HIGH(c1), 2482 TCGV_LOW(c2), TCGV_HIGH(c2), cond); 2483 2484 if (TCG_TARGET_HAS_movcond_i32) { 2485 tcg_gen_movi_i32(t1, 0); 2486 tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1, 2487 TCGV_LOW(v1), TCGV_LOW(v2)); 2488 tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1, 2489 TCGV_HIGH(v1), TCGV_HIGH(v2)); 2490 } else { 2491 tcg_gen_neg_i32(t0, t0); 2492 2493 tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); 2494 tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); 2495 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); 2496 2497 tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); 2498 tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); 2499 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); 2500 } 2501 tcg_temp_free_i32(t0); 2502 tcg_temp_free_i32(t1); 2503 } else if (TCG_TARGET_HAS_movcond_i64) { 2504 tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); 2505 } else { 2506 TCGv_i64 t0 = tcg_temp_new_i64(); 2507 TCGv_i64 t1 = tcg_temp_new_i64(); 2508 tcg_gen_setcond_i64(cond, t0, c1, c2); 2509 tcg_gen_neg_i64(t0, t0); 2510 tcg_gen_and_i64(t1, v1, t0); 2511 tcg_gen_andc_i64(ret, v2, t0); 2512 tcg_gen_or_i64(ret, ret, t1); 2513 tcg_temp_free_i64(t0); 2514 tcg_temp_free_i64(t1); 2515 } 2516 } 2517 2518 void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2519 TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2520 { 2521 if (TCG_TARGET_HAS_add2_i64) { 2522 tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh); 2523 } else { 2524 TCGv_i64 t0 = tcg_temp_new_i64(); 2525 TCGv_i64 t1 = tcg_temp_new_i64(); 2526 tcg_gen_add_i64(t0, al, bl); 2527 tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al); 2528 tcg_gen_add_i64(rh, ah, bh); 2529 tcg_gen_add_i64(rh, rh, t1); 2530 tcg_gen_mov_i64(rl, t0); 2531 tcg_temp_free_i64(t0); 2532 tcg_temp_free_i64(t1); 2533 } 2534 } 2535 2536 void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2537 TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2538 { 2539 if (TCG_TARGET_HAS_sub2_i64) { 2540 tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh); 2541 } else { 2542 TCGv_i64 t0 = tcg_temp_new_i64(); 2543 TCGv_i64 t1 = tcg_temp_new_i64(); 2544 tcg_gen_sub_i64(t0, al, bl); 2545 tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl); 2546 tcg_gen_sub_i64(rh, ah, bh); 2547 tcg_gen_sub_i64(rh, rh, t1); 2548 tcg_gen_mov_i64(rl, t0); 2549 tcg_temp_free_i64(t0); 2550 tcg_temp_free_i64(t1); 2551 } 2552 } 2553 2554 void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2555 { 2556 if (TCG_TARGET_HAS_mulu2_i64) { 2557 tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); 2558 } else if (TCG_TARGET_HAS_muluh_i64) { 2559 TCGv_i64 t = tcg_temp_new_i64(); 2560 tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2561 tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2); 2562 tcg_gen_mov_i64(rl, t); 2563 tcg_temp_free_i64(t); 2564 } else { 2565 TCGv_i64 t0 = tcg_temp_new_i64(); 2566 tcg_gen_mul_i64(t0, arg1, arg2); 2567 gen_helper_muluh_i64(rh, arg1, arg2); 2568 tcg_gen_mov_i64(rl, t0); 2569 tcg_temp_free_i64(t0); 2570 } 2571 } 2572 2573 void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2574 { 2575 if (TCG_TARGET_HAS_muls2_i64) { 2576 tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); 2577 } else if (TCG_TARGET_HAS_mulsh_i64) { 2578 TCGv_i64 t = tcg_temp_new_i64(); 2579 tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2580 tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2); 2581 tcg_gen_mov_i64(rl, t); 2582 tcg_temp_free_i64(t); 2583 } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) { 2584 TCGv_i64 t0 = tcg_temp_new_i64(); 2585 TCGv_i64 t1 = tcg_temp_new_i64(); 2586 TCGv_i64 t2 = tcg_temp_new_i64(); 2587 TCGv_i64 t3 = tcg_temp_new_i64(); 2588 tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 2589 /* Adjust for negative inputs. */ 2590 tcg_gen_sari_i64(t2, arg1, 63); 2591 tcg_gen_sari_i64(t3, arg2, 63); 2592 tcg_gen_and_i64(t2, t2, arg2); 2593 tcg_gen_and_i64(t3, t3, arg1); 2594 tcg_gen_sub_i64(rh, t1, t2); 2595 tcg_gen_sub_i64(rh, rh, t3); 2596 tcg_gen_mov_i64(rl, t0); 2597 tcg_temp_free_i64(t0); 2598 tcg_temp_free_i64(t1); 2599 tcg_temp_free_i64(t2); 2600 tcg_temp_free_i64(t3); 2601 } else { 2602 TCGv_i64 t0 = tcg_temp_new_i64(); 2603 tcg_gen_mul_i64(t0, arg1, arg2); 2604 gen_helper_mulsh_i64(rh, arg1, arg2); 2605 tcg_gen_mov_i64(rl, t0); 2606 tcg_temp_free_i64(t0); 2607 } 2608 } 2609 2610 void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2611 { 2612 TCGv_i64 t0 = tcg_temp_new_i64(); 2613 TCGv_i64 t1 = tcg_temp_new_i64(); 2614 TCGv_i64 t2 = tcg_temp_new_i64(); 2615 tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 2616 /* Adjust for negative input for the signed arg1. */ 2617 tcg_gen_sari_i64(t2, arg1, 63); 2618 tcg_gen_and_i64(t2, t2, arg2); 2619 tcg_gen_sub_i64(rh, t1, t2); 2620 tcg_gen_mov_i64(rl, t0); 2621 tcg_temp_free_i64(t0); 2622 tcg_temp_free_i64(t1); 2623 tcg_temp_free_i64(t2); 2624 } 2625 2626 void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2627 { 2628 tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); 2629 } 2630 2631 void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2632 { 2633 tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); 2634 } 2635 2636 void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2637 { 2638 tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); 2639 } 2640 2641 void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2642 { 2643 tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); 2644 } 2645 2646 void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a) 2647 { 2648 TCGv_i64 t = tcg_temp_new_i64(); 2649 2650 tcg_gen_sari_i64(t, a, 63); 2651 tcg_gen_xor_i64(ret, a, t); 2652 tcg_gen_sub_i64(ret, ret, t); 2653 tcg_temp_free_i64(t); 2654 } 2655 2656 /* Size changing operations. */ 2657 2658 void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2659 { 2660 if (TCG_TARGET_REG_BITS == 32) { 2661 tcg_gen_mov_i32(ret, TCGV_LOW(arg)); 2662 } else if (TCG_TARGET_HAS_extrl_i64_i32) { 2663 tcg_gen_op2(INDEX_op_extrl_i64_i32, 2664 tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2665 } else { 2666 tcg_gen_mov_i32(ret, (TCGv_i32)arg); 2667 } 2668 } 2669 2670 void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2671 { 2672 if (TCG_TARGET_REG_BITS == 32) { 2673 tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); 2674 } else if (TCG_TARGET_HAS_extrh_i64_i32) { 2675 tcg_gen_op2(INDEX_op_extrh_i64_i32, 2676 tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2677 } else { 2678 TCGv_i64 t = tcg_temp_new_i64(); 2679 tcg_gen_shri_i64(t, arg, 32); 2680 tcg_gen_mov_i32(ret, (TCGv_i32)t); 2681 tcg_temp_free_i64(t); 2682 } 2683 } 2684 2685 void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2686 { 2687 if (TCG_TARGET_REG_BITS == 32) { 2688 tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2689 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2690 } else { 2691 tcg_gen_op2(INDEX_op_extu_i32_i64, 2692 tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 2693 } 2694 } 2695 2696 void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2697 { 2698 if (TCG_TARGET_REG_BITS == 32) { 2699 tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2700 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 2701 } else { 2702 tcg_gen_op2(INDEX_op_ext_i32_i64, 2703 tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 2704 } 2705 } 2706 2707 void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) 2708 { 2709 TCGv_i64 tmp; 2710 2711 if (TCG_TARGET_REG_BITS == 32) { 2712 tcg_gen_mov_i32(TCGV_LOW(dest), low); 2713 tcg_gen_mov_i32(TCGV_HIGH(dest), high); 2714 return; 2715 } 2716 2717 tmp = tcg_temp_new_i64(); 2718 /* These extensions are only needed for type correctness. 2719 We may be able to do better given target specific information. */ 2720 tcg_gen_extu_i32_i64(tmp, high); 2721 tcg_gen_extu_i32_i64(dest, low); 2722 /* If deposit is available, use it. Otherwise use the extra 2723 knowledge that we have of the zero-extensions above. */ 2724 if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { 2725 tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); 2726 } else { 2727 tcg_gen_shli_i64(tmp, tmp, 32); 2728 tcg_gen_or_i64(dest, dest, tmp); 2729 } 2730 tcg_temp_free_i64(tmp); 2731 } 2732 2733 void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg) 2734 { 2735 if (TCG_TARGET_REG_BITS == 32) { 2736 tcg_gen_mov_i32(lo, TCGV_LOW(arg)); 2737 tcg_gen_mov_i32(hi, TCGV_HIGH(arg)); 2738 } else { 2739 tcg_gen_extrl_i64_i32(lo, arg); 2740 tcg_gen_extrh_i64_i32(hi, arg); 2741 } 2742 } 2743 2744 void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) 2745 { 2746 tcg_gen_ext32u_i64(lo, arg); 2747 tcg_gen_shri_i64(hi, arg, 32); 2748 } 2749 2750 void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg) 2751 { 2752 tcg_gen_mov_i64(lo, TCGV128_LOW(arg)); 2753 tcg_gen_mov_i64(hi, TCGV128_HIGH(arg)); 2754 } 2755 2756 void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi) 2757 { 2758 tcg_gen_mov_i64(TCGV128_LOW(ret), lo); 2759 tcg_gen_mov_i64(TCGV128_HIGH(ret), hi); 2760 } 2761 2762 void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src) 2763 { 2764 if (dst != src) { 2765 tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src)); 2766 tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src)); 2767 } 2768 } 2769 2770 /* QEMU specific operations. */ 2771 2772 void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx) 2773 { 2774 /* 2775 * Let the jit code return the read-only version of the 2776 * TranslationBlock, so that we minimize the pc-relative 2777 * distance of the address of the exit_tb code to TB. 2778 * This will improve utilization of pc-relative address loads. 2779 * 2780 * TODO: Move this to translator_loop, so that all const 2781 * TranslationBlock pointers refer to read-only memory. 2782 * This requires coordination with targets that do not use 2783 * the translator_loop. 2784 */ 2785 uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx; 2786 2787 if (tb == NULL) { 2788 tcg_debug_assert(idx == 0); 2789 } else if (idx <= TB_EXIT_IDXMAX) { 2790 #ifdef CONFIG_DEBUG_TCG 2791 /* This is an exit following a goto_tb. Verify that we have 2792 seen this numbered exit before, via tcg_gen_goto_tb. */ 2793 tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); 2794 #endif 2795 } else { 2796 /* This is an exit via the exitreq label. */ 2797 tcg_debug_assert(idx == TB_EXIT_REQUESTED); 2798 } 2799 2800 plugin_gen_disable_mem_helpers(); 2801 tcg_gen_op1i(INDEX_op_exit_tb, val); 2802 } 2803 2804 void tcg_gen_goto_tb(unsigned idx) 2805 { 2806 /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */ 2807 tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB)); 2808 /* We only support two chained exits. */ 2809 tcg_debug_assert(idx <= TB_EXIT_IDXMAX); 2810 #ifdef CONFIG_DEBUG_TCG 2811 /* Verify that we haven't seen this numbered exit before. */ 2812 tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0); 2813 tcg_ctx->goto_tb_issue_mask |= 1 << idx; 2814 #endif 2815 plugin_gen_disable_mem_helpers(); 2816 tcg_gen_op1i(INDEX_op_goto_tb, idx); 2817 } 2818 2819 void tcg_gen_lookup_and_goto_ptr(void) 2820 { 2821 TCGv_ptr ptr; 2822 2823 if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) { 2824 tcg_gen_exit_tb(NULL, 0); 2825 return; 2826 } 2827 2828 plugin_gen_disable_mem_helpers(); 2829 ptr = tcg_temp_new_ptr(); 2830 gen_helper_lookup_tb_ptr(ptr, cpu_env); 2831 tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr)); 2832 tcg_temp_free_ptr(ptr); 2833 } 2834 2835 static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st) 2836 { 2837 /* Trigger the asserts within as early as possible. */ 2838 unsigned a_bits = get_alignment_bits(op); 2839 2840 /* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */ 2841 if (a_bits == (op & MO_SIZE)) { 2842 op = (op & ~MO_AMASK) | MO_ALIGN; 2843 } 2844 2845 switch (op & MO_SIZE) { 2846 case MO_8: 2847 op &= ~MO_BSWAP; 2848 break; 2849 case MO_16: 2850 break; 2851 case MO_32: 2852 if (!is64) { 2853 op &= ~MO_SIGN; 2854 } 2855 break; 2856 case MO_64: 2857 if (is64) { 2858 op &= ~MO_SIGN; 2859 break; 2860 } 2861 /* fall through */ 2862 default: 2863 g_assert_not_reached(); 2864 } 2865 if (st) { 2866 op &= ~MO_SIGN; 2867 } 2868 return op; 2869 } 2870 2871 static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr, 2872 MemOp memop, TCGArg idx) 2873 { 2874 MemOpIdx oi = make_memop_idx(memop, idx); 2875 #if TARGET_LONG_BITS == 32 2876 tcg_gen_op3i_i32(opc, val, addr, oi); 2877 #else 2878 if (TCG_TARGET_REG_BITS == 32) { 2879 tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi); 2880 } else { 2881 tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi); 2882 } 2883 #endif 2884 } 2885 2886 static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr, 2887 MemOp memop, TCGArg idx) 2888 { 2889 MemOpIdx oi = make_memop_idx(memop, idx); 2890 #if TARGET_LONG_BITS == 32 2891 if (TCG_TARGET_REG_BITS == 32) { 2892 tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi); 2893 } else { 2894 tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi); 2895 } 2896 #else 2897 if (TCG_TARGET_REG_BITS == 32) { 2898 tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), 2899 TCGV_LOW(addr), TCGV_HIGH(addr), oi); 2900 } else { 2901 tcg_gen_op3i_i64(opc, val, addr, oi); 2902 } 2903 #endif 2904 } 2905 2906 static void tcg_gen_req_mo(TCGBar type) 2907 { 2908 #ifdef TCG_GUEST_DEFAULT_MO 2909 type &= TCG_GUEST_DEFAULT_MO; 2910 #endif 2911 type &= ~TCG_TARGET_DEFAULT_MO; 2912 if (type) { 2913 tcg_gen_mb(type | TCG_BAR_SC); 2914 } 2915 } 2916 2917 static inline TCGv plugin_prep_mem_callbacks(TCGv vaddr) 2918 { 2919 #ifdef CONFIG_PLUGIN 2920 if (tcg_ctx->plugin_insn != NULL) { 2921 /* Save a copy of the vaddr for use after a load. */ 2922 TCGv temp = tcg_temp_new(); 2923 tcg_gen_mov_tl(temp, vaddr); 2924 return temp; 2925 } 2926 #endif 2927 return vaddr; 2928 } 2929 2930 static void plugin_gen_mem_callbacks(TCGv vaddr, MemOpIdx oi, 2931 enum qemu_plugin_mem_rw rw) 2932 { 2933 #ifdef CONFIG_PLUGIN 2934 if (tcg_ctx->plugin_insn != NULL) { 2935 qemu_plugin_meminfo_t info = make_plugin_meminfo(oi, rw); 2936 plugin_gen_empty_mem_callback(vaddr, info); 2937 tcg_temp_free(vaddr); 2938 } 2939 #endif 2940 } 2941 2942 void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop) 2943 { 2944 MemOp orig_memop; 2945 MemOpIdx oi; 2946 2947 tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD); 2948 memop = tcg_canonicalize_memop(memop, 0, 0); 2949 oi = make_memop_idx(memop, idx); 2950 2951 orig_memop = memop; 2952 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 2953 memop &= ~MO_BSWAP; 2954 /* The bswap primitive benefits from zero-extended input. */ 2955 if ((memop & MO_SSIZE) == MO_SW) { 2956 memop &= ~MO_SIGN; 2957 } 2958 } 2959 2960 addr = plugin_prep_mem_callbacks(addr); 2961 gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx); 2962 plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R); 2963 2964 if ((orig_memop ^ memop) & MO_BSWAP) { 2965 switch (orig_memop & MO_SIZE) { 2966 case MO_16: 2967 tcg_gen_bswap16_i32(val, val, (orig_memop & MO_SIGN 2968 ? TCG_BSWAP_IZ | TCG_BSWAP_OS 2969 : TCG_BSWAP_IZ | TCG_BSWAP_OZ)); 2970 break; 2971 case MO_32: 2972 tcg_gen_bswap32_i32(val, val); 2973 break; 2974 default: 2975 g_assert_not_reached(); 2976 } 2977 } 2978 } 2979 2980 void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop) 2981 { 2982 TCGv_i32 swap = NULL; 2983 MemOpIdx oi; 2984 2985 tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST); 2986 memop = tcg_canonicalize_memop(memop, 0, 1); 2987 oi = make_memop_idx(memop, idx); 2988 2989 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 2990 swap = tcg_temp_new_i32(); 2991 switch (memop & MO_SIZE) { 2992 case MO_16: 2993 tcg_gen_bswap16_i32(swap, val, 0); 2994 break; 2995 case MO_32: 2996 tcg_gen_bswap32_i32(swap, val); 2997 break; 2998 default: 2999 g_assert_not_reached(); 3000 } 3001 val = swap; 3002 memop &= ~MO_BSWAP; 3003 } 3004 3005 addr = plugin_prep_mem_callbacks(addr); 3006 if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) { 3007 gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx); 3008 } else { 3009 gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx); 3010 } 3011 plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W); 3012 3013 if (swap) { 3014 tcg_temp_free_i32(swap); 3015 } 3016 } 3017 3018 void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop) 3019 { 3020 MemOp orig_memop; 3021 MemOpIdx oi; 3022 3023 if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) { 3024 tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop); 3025 if (memop & MO_SIGN) { 3026 tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31); 3027 } else { 3028 tcg_gen_movi_i32(TCGV_HIGH(val), 0); 3029 } 3030 return; 3031 } 3032 3033 tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD); 3034 memop = tcg_canonicalize_memop(memop, 1, 0); 3035 oi = make_memop_idx(memop, idx); 3036 3037 orig_memop = memop; 3038 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 3039 memop &= ~MO_BSWAP; 3040 /* The bswap primitive benefits from zero-extended input. */ 3041 if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) { 3042 memop &= ~MO_SIGN; 3043 } 3044 } 3045 3046 addr = plugin_prep_mem_callbacks(addr); 3047 gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx); 3048 plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R); 3049 3050 if ((orig_memop ^ memop) & MO_BSWAP) { 3051 int flags = (orig_memop & MO_SIGN 3052 ? TCG_BSWAP_IZ | TCG_BSWAP_OS 3053 : TCG_BSWAP_IZ | TCG_BSWAP_OZ); 3054 switch (orig_memop & MO_SIZE) { 3055 case MO_16: 3056 tcg_gen_bswap16_i64(val, val, flags); 3057 break; 3058 case MO_32: 3059 tcg_gen_bswap32_i64(val, val, flags); 3060 break; 3061 case MO_64: 3062 tcg_gen_bswap64_i64(val, val); 3063 break; 3064 default: 3065 g_assert_not_reached(); 3066 } 3067 } 3068 } 3069 3070 void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop) 3071 { 3072 TCGv_i64 swap = NULL; 3073 MemOpIdx oi; 3074 3075 if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) { 3076 tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop); 3077 return; 3078 } 3079 3080 tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST); 3081 memop = tcg_canonicalize_memop(memop, 1, 1); 3082 oi = make_memop_idx(memop, idx); 3083 3084 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 3085 swap = tcg_temp_new_i64(); 3086 switch (memop & MO_SIZE) { 3087 case MO_16: 3088 tcg_gen_bswap16_i64(swap, val, 0); 3089 break; 3090 case MO_32: 3091 tcg_gen_bswap32_i64(swap, val, 0); 3092 break; 3093 case MO_64: 3094 tcg_gen_bswap64_i64(swap, val); 3095 break; 3096 default: 3097 g_assert_not_reached(); 3098 } 3099 val = swap; 3100 memop &= ~MO_BSWAP; 3101 } 3102 3103 addr = plugin_prep_mem_callbacks(addr); 3104 gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx); 3105 plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W); 3106 3107 if (swap) { 3108 tcg_temp_free_i64(swap); 3109 } 3110 } 3111 3112 static void canonicalize_memop_i128_as_i64(MemOp ret[2], MemOp orig) 3113 { 3114 MemOp mop_1 = orig, mop_2; 3115 3116 tcg_debug_assert((orig & MO_SIZE) == MO_128); 3117 tcg_debug_assert((orig & MO_SIGN) == 0); 3118 3119 /* Use a memory ordering implemented by the host. */ 3120 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (orig & MO_BSWAP)) { 3121 mop_1 &= ~MO_BSWAP; 3122 } 3123 3124 /* Reduce the size to 64-bit. */ 3125 mop_1 = (mop_1 & ~MO_SIZE) | MO_64; 3126 3127 /* Retain the alignment constraints of the original. */ 3128 switch (orig & MO_AMASK) { 3129 case MO_UNALN: 3130 case MO_ALIGN_2: 3131 case MO_ALIGN_4: 3132 mop_2 = mop_1; 3133 break; 3134 case MO_ALIGN_8: 3135 /* Prefer MO_ALIGN+MO_64 to MO_ALIGN_8+MO_64. */ 3136 mop_1 = (mop_1 & ~MO_AMASK) | MO_ALIGN; 3137 mop_2 = mop_1; 3138 break; 3139 case MO_ALIGN: 3140 /* Second has 8-byte alignment; first has 16-byte alignment. */ 3141 mop_2 = mop_1; 3142 mop_1 = (mop_1 & ~MO_AMASK) | MO_ALIGN_16; 3143 break; 3144 case MO_ALIGN_16: 3145 case MO_ALIGN_32: 3146 case MO_ALIGN_64: 3147 /* Second has 8-byte alignment; first retains original. */ 3148 mop_2 = (mop_1 & ~MO_AMASK) | MO_ALIGN; 3149 break; 3150 default: 3151 g_assert_not_reached(); 3152 } 3153 ret[0] = mop_1; 3154 ret[1] = mop_2; 3155 } 3156 3157 void tcg_gen_qemu_ld_i128(TCGv_i128 val, TCGv addr, TCGArg idx, MemOp memop) 3158 { 3159 MemOp mop[2]; 3160 TCGv addr_p8; 3161 TCGv_i64 x, y; 3162 3163 canonicalize_memop_i128_as_i64(mop, memop); 3164 3165 tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD); 3166 addr = plugin_prep_mem_callbacks(addr); 3167 3168 /* TODO: respect atomicity of the operation. */ 3169 /* TODO: allow the tcg backend to see the whole operation. */ 3170 3171 /* 3172 * Since there are no global TCGv_i128, there is no visible state 3173 * changed if the second load faults. Load directly into the two 3174 * subwords. 3175 */ 3176 if ((memop & MO_BSWAP) == MO_LE) { 3177 x = TCGV128_LOW(val); 3178 y = TCGV128_HIGH(val); 3179 } else { 3180 x = TCGV128_HIGH(val); 3181 y = TCGV128_LOW(val); 3182 } 3183 3184 gen_ldst_i64(INDEX_op_qemu_ld_i64, x, addr, mop[0], idx); 3185 3186 if ((mop[0] ^ memop) & MO_BSWAP) { 3187 tcg_gen_bswap64_i64(x, x); 3188 } 3189 3190 addr_p8 = tcg_temp_new(); 3191 tcg_gen_addi_tl(addr_p8, addr, 8); 3192 gen_ldst_i64(INDEX_op_qemu_ld_i64, y, addr_p8, mop[1], idx); 3193 tcg_temp_free(addr_p8); 3194 3195 if ((mop[0] ^ memop) & MO_BSWAP) { 3196 tcg_gen_bswap64_i64(y, y); 3197 } 3198 3199 plugin_gen_mem_callbacks(addr, make_memop_idx(memop, idx), 3200 QEMU_PLUGIN_MEM_R); 3201 } 3202 3203 void tcg_gen_qemu_st_i128(TCGv_i128 val, TCGv addr, TCGArg idx, MemOp memop) 3204 { 3205 MemOp mop[2]; 3206 TCGv addr_p8; 3207 TCGv_i64 x, y; 3208 3209 canonicalize_memop_i128_as_i64(mop, memop); 3210 3211 tcg_gen_req_mo(TCG_MO_ST_LD | TCG_MO_ST_ST); 3212 addr = plugin_prep_mem_callbacks(addr); 3213 3214 /* TODO: respect atomicity of the operation. */ 3215 /* TODO: allow the tcg backend to see the whole operation. */ 3216 3217 if ((memop & MO_BSWAP) == MO_LE) { 3218 x = TCGV128_LOW(val); 3219 y = TCGV128_HIGH(val); 3220 } else { 3221 x = TCGV128_HIGH(val); 3222 y = TCGV128_LOW(val); 3223 } 3224 3225 addr_p8 = tcg_temp_new(); 3226 if ((mop[0] ^ memop) & MO_BSWAP) { 3227 TCGv_i64 t = tcg_temp_new_i64(); 3228 3229 tcg_gen_bswap64_i64(t, x); 3230 gen_ldst_i64(INDEX_op_qemu_st_i64, t, addr, mop[0], idx); 3231 tcg_gen_bswap64_i64(t, y); 3232 tcg_gen_addi_tl(addr_p8, addr, 8); 3233 gen_ldst_i64(INDEX_op_qemu_st_i64, t, addr_p8, mop[1], idx); 3234 tcg_temp_free_i64(t); 3235 } else { 3236 gen_ldst_i64(INDEX_op_qemu_st_i64, x, addr, mop[0], idx); 3237 tcg_gen_addi_tl(addr_p8, addr, 8); 3238 gen_ldst_i64(INDEX_op_qemu_st_i64, y, addr_p8, mop[1], idx); 3239 } 3240 tcg_temp_free(addr_p8); 3241 3242 plugin_gen_mem_callbacks(addr, make_memop_idx(memop, idx), 3243 QEMU_PLUGIN_MEM_W); 3244 } 3245 3246 static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc) 3247 { 3248 switch (opc & MO_SSIZE) { 3249 case MO_SB: 3250 tcg_gen_ext8s_i32(ret, val); 3251 break; 3252 case MO_UB: 3253 tcg_gen_ext8u_i32(ret, val); 3254 break; 3255 case MO_SW: 3256 tcg_gen_ext16s_i32(ret, val); 3257 break; 3258 case MO_UW: 3259 tcg_gen_ext16u_i32(ret, val); 3260 break; 3261 default: 3262 tcg_gen_mov_i32(ret, val); 3263 break; 3264 } 3265 } 3266 3267 static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc) 3268 { 3269 switch (opc & MO_SSIZE) { 3270 case MO_SB: 3271 tcg_gen_ext8s_i64(ret, val); 3272 break; 3273 case MO_UB: 3274 tcg_gen_ext8u_i64(ret, val); 3275 break; 3276 case MO_SW: 3277 tcg_gen_ext16s_i64(ret, val); 3278 break; 3279 case MO_UW: 3280 tcg_gen_ext16u_i64(ret, val); 3281 break; 3282 case MO_SL: 3283 tcg_gen_ext32s_i64(ret, val); 3284 break; 3285 case MO_UL: 3286 tcg_gen_ext32u_i64(ret, val); 3287 break; 3288 default: 3289 tcg_gen_mov_i64(ret, val); 3290 break; 3291 } 3292 } 3293 3294 typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, 3295 TCGv_i32, TCGv_i32, TCGv_i32); 3296 typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, 3297 TCGv_i64, TCGv_i64, TCGv_i32); 3298 typedef void (*gen_atomic_cx_i128)(TCGv_i128, TCGv_env, TCGv, 3299 TCGv_i128, TCGv_i128, TCGv_i32); 3300 typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, 3301 TCGv_i32, TCGv_i32); 3302 typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, 3303 TCGv_i64, TCGv_i32); 3304 3305 #ifdef CONFIG_ATOMIC64 3306 # define WITH_ATOMIC64(X) X, 3307 #else 3308 # define WITH_ATOMIC64(X) 3309 #endif 3310 #ifdef CONFIG_CMPXCHG128 3311 # define WITH_ATOMIC128(X) X, 3312 #else 3313 # define WITH_ATOMIC128(X) 3314 #endif 3315 3316 static void * const table_cmpxchg[(MO_SIZE | MO_BSWAP) + 1] = { 3317 [MO_8] = gen_helper_atomic_cmpxchgb, 3318 [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le, 3319 [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be, 3320 [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le, 3321 [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be, 3322 WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le) 3323 WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be) 3324 WITH_ATOMIC128([MO_128 | MO_LE] = gen_helper_atomic_cmpxchgo_le) 3325 WITH_ATOMIC128([MO_128 | MO_BE] = gen_helper_atomic_cmpxchgo_be) 3326 }; 3327 3328 void tcg_gen_nonatomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv, 3329 TCGv_i32 newv, TCGArg idx, MemOp memop) 3330 { 3331 TCGv_i32 t1 = tcg_temp_new_i32(); 3332 TCGv_i32 t2 = tcg_temp_new_i32(); 3333 3334 tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE); 3335 3336 tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN); 3337 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1); 3338 tcg_gen_qemu_st_i32(t2, addr, idx, memop); 3339 tcg_temp_free_i32(t2); 3340 3341 if (memop & MO_SIGN) { 3342 tcg_gen_ext_i32(retv, t1, memop); 3343 } else { 3344 tcg_gen_mov_i32(retv, t1); 3345 } 3346 tcg_temp_free_i32(t1); 3347 } 3348 3349 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv, 3350 TCGv_i32 newv, TCGArg idx, MemOp memop) 3351 { 3352 gen_atomic_cx_i32 gen; 3353 MemOpIdx oi; 3354 3355 if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { 3356 tcg_gen_nonatomic_cmpxchg_i32(retv, addr, cmpv, newv, idx, memop); 3357 return; 3358 } 3359 3360 memop = tcg_canonicalize_memop(memop, 0, 0); 3361 gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)]; 3362 tcg_debug_assert(gen != NULL); 3363 3364 oi = make_memop_idx(memop & ~MO_SIGN, idx); 3365 gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi)); 3366 3367 if (memop & MO_SIGN) { 3368 tcg_gen_ext_i32(retv, retv, memop); 3369 } 3370 } 3371 3372 void tcg_gen_nonatomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv, 3373 TCGv_i64 newv, TCGArg idx, MemOp memop) 3374 { 3375 TCGv_i64 t1, t2; 3376 3377 if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) { 3378 tcg_gen_nonatomic_cmpxchg_i32(TCGV_LOW(retv), addr, TCGV_LOW(cmpv), 3379 TCGV_LOW(newv), idx, memop); 3380 if (memop & MO_SIGN) { 3381 tcg_gen_sari_i32(TCGV_HIGH(retv), TCGV_LOW(retv), 31); 3382 } else { 3383 tcg_gen_movi_i32(TCGV_HIGH(retv), 0); 3384 } 3385 return; 3386 } 3387 3388 t1 = tcg_temp_new_i64(); 3389 t2 = tcg_temp_new_i64(); 3390 3391 tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE); 3392 3393 tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN); 3394 tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1); 3395 tcg_gen_qemu_st_i64(t2, addr, idx, memop); 3396 tcg_temp_free_i64(t2); 3397 3398 if (memop & MO_SIGN) { 3399 tcg_gen_ext_i64(retv, t1, memop); 3400 } else { 3401 tcg_gen_mov_i64(retv, t1); 3402 } 3403 tcg_temp_free_i64(t1); 3404 } 3405 3406 void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv, 3407 TCGv_i64 newv, TCGArg idx, MemOp memop) 3408 { 3409 if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { 3410 tcg_gen_nonatomic_cmpxchg_i64(retv, addr, cmpv, newv, idx, memop); 3411 return; 3412 } 3413 3414 if ((memop & MO_SIZE) == MO_64) { 3415 gen_atomic_cx_i64 gen; 3416 3417 memop = tcg_canonicalize_memop(memop, 1, 0); 3418 gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)]; 3419 if (gen) { 3420 MemOpIdx oi = make_memop_idx(memop, idx); 3421 gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi)); 3422 return; 3423 } 3424 3425 gen_helper_exit_atomic(cpu_env); 3426 3427 /* 3428 * Produce a result for a well-formed opcode stream. This satisfies 3429 * liveness for set before used, which happens before this dead code 3430 * is removed. 3431 */ 3432 tcg_gen_movi_i64(retv, 0); 3433 return; 3434 } 3435 3436 if (TCG_TARGET_REG_BITS == 32) { 3437 tcg_gen_atomic_cmpxchg_i32(TCGV_LOW(retv), addr, TCGV_LOW(cmpv), 3438 TCGV_LOW(newv), idx, memop); 3439 if (memop & MO_SIGN) { 3440 tcg_gen_sari_i32(TCGV_HIGH(retv), TCGV_LOW(retv), 31); 3441 } else { 3442 tcg_gen_movi_i32(TCGV_HIGH(retv), 0); 3443 } 3444 } else { 3445 TCGv_i32 c32 = tcg_temp_new_i32(); 3446 TCGv_i32 n32 = tcg_temp_new_i32(); 3447 TCGv_i32 r32 = tcg_temp_new_i32(); 3448 3449 tcg_gen_extrl_i64_i32(c32, cmpv); 3450 tcg_gen_extrl_i64_i32(n32, newv); 3451 tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN); 3452 tcg_temp_free_i32(c32); 3453 tcg_temp_free_i32(n32); 3454 3455 tcg_gen_extu_i32_i64(retv, r32); 3456 tcg_temp_free_i32(r32); 3457 3458 if (memop & MO_SIGN) { 3459 tcg_gen_ext_i64(retv, retv, memop); 3460 } 3461 } 3462 } 3463 3464 void tcg_gen_nonatomic_cmpxchg_i128(TCGv_i128 retv, TCGv addr, TCGv_i128 cmpv, 3465 TCGv_i128 newv, TCGArg idx, MemOp memop) 3466 { 3467 if (TCG_TARGET_REG_BITS == 32) { 3468 /* Inline expansion below is simply too large for 32-bit hosts. */ 3469 gen_atomic_cx_i128 gen = ((memop & MO_BSWAP) == MO_LE 3470 ? gen_helper_nonatomic_cmpxchgo_le 3471 : gen_helper_nonatomic_cmpxchgo_be); 3472 MemOpIdx oi = make_memop_idx(memop, idx); 3473 3474 tcg_debug_assert((memop & MO_SIZE) == MO_128); 3475 tcg_debug_assert((memop & MO_SIGN) == 0); 3476 3477 gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi)); 3478 } else { 3479 TCGv_i128 oldv = tcg_temp_new_i128(); 3480 TCGv_i128 tmpv = tcg_temp_new_i128(); 3481 TCGv_i64 t0 = tcg_temp_new_i64(); 3482 TCGv_i64 t1 = tcg_temp_new_i64(); 3483 TCGv_i64 z = tcg_constant_i64(0); 3484 3485 tcg_gen_qemu_ld_i128(oldv, addr, idx, memop); 3486 3487 /* Compare i128 */ 3488 tcg_gen_xor_i64(t0, TCGV128_LOW(oldv), TCGV128_LOW(cmpv)); 3489 tcg_gen_xor_i64(t1, TCGV128_HIGH(oldv), TCGV128_HIGH(cmpv)); 3490 tcg_gen_or_i64(t0, t0, t1); 3491 3492 /* tmpv = equal ? newv : oldv */ 3493 tcg_gen_movcond_i64(TCG_COND_EQ, TCGV128_LOW(tmpv), t0, z, 3494 TCGV128_LOW(newv), TCGV128_LOW(oldv)); 3495 tcg_gen_movcond_i64(TCG_COND_EQ, TCGV128_HIGH(tmpv), t0, z, 3496 TCGV128_HIGH(newv), TCGV128_HIGH(oldv)); 3497 3498 /* Unconditional writeback. */ 3499 tcg_gen_qemu_st_i128(tmpv, addr, idx, memop); 3500 tcg_gen_mov_i128(retv, oldv); 3501 3502 tcg_temp_free_i64(t0); 3503 tcg_temp_free_i64(t1); 3504 tcg_temp_free_i128(tmpv); 3505 tcg_temp_free_i128(oldv); 3506 } 3507 } 3508 3509 void tcg_gen_atomic_cmpxchg_i128(TCGv_i128 retv, TCGv addr, TCGv_i128 cmpv, 3510 TCGv_i128 newv, TCGArg idx, MemOp memop) 3511 { 3512 gen_atomic_cx_i128 gen; 3513 3514 if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { 3515 tcg_gen_nonatomic_cmpxchg_i128(retv, addr, cmpv, newv, idx, memop); 3516 return; 3517 } 3518 3519 tcg_debug_assert((memop & MO_SIZE) == MO_128); 3520 tcg_debug_assert((memop & MO_SIGN) == 0); 3521 gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)]; 3522 3523 if (gen) { 3524 MemOpIdx oi = make_memop_idx(memop, idx); 3525 gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi)); 3526 return; 3527 } 3528 3529 gen_helper_exit_atomic(cpu_env); 3530 3531 /* 3532 * Produce a result for a well-formed opcode stream. This satisfies 3533 * liveness for set before used, which happens before this dead code 3534 * is removed. 3535 */ 3536 tcg_gen_movi_i64(TCGV128_LOW(retv), 0); 3537 tcg_gen_movi_i64(TCGV128_HIGH(retv), 0); 3538 } 3539 3540 static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val, 3541 TCGArg idx, MemOp memop, bool new_val, 3542 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32)) 3543 { 3544 TCGv_i32 t1 = tcg_temp_new_i32(); 3545 TCGv_i32 t2 = tcg_temp_new_i32(); 3546 3547 memop = tcg_canonicalize_memop(memop, 0, 0); 3548 3549 tcg_gen_qemu_ld_i32(t1, addr, idx, memop); 3550 tcg_gen_ext_i32(t2, val, memop); 3551 gen(t2, t1, t2); 3552 tcg_gen_qemu_st_i32(t2, addr, idx, memop); 3553 3554 tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop); 3555 tcg_temp_free_i32(t1); 3556 tcg_temp_free_i32(t2); 3557 } 3558 3559 static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val, 3560 TCGArg idx, MemOp memop, void * const table[]) 3561 { 3562 gen_atomic_op_i32 gen; 3563 MemOpIdx oi; 3564 3565 memop = tcg_canonicalize_memop(memop, 0, 0); 3566 3567 gen = table[memop & (MO_SIZE | MO_BSWAP)]; 3568 tcg_debug_assert(gen != NULL); 3569 3570 oi = make_memop_idx(memop & ~MO_SIGN, idx); 3571 gen(ret, cpu_env, addr, val, tcg_constant_i32(oi)); 3572 3573 if (memop & MO_SIGN) { 3574 tcg_gen_ext_i32(ret, ret, memop); 3575 } 3576 } 3577 3578 static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val, 3579 TCGArg idx, MemOp memop, bool new_val, 3580 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64)) 3581 { 3582 TCGv_i64 t1 = tcg_temp_new_i64(); 3583 TCGv_i64 t2 = tcg_temp_new_i64(); 3584 3585 memop = tcg_canonicalize_memop(memop, 1, 0); 3586 3587 tcg_gen_qemu_ld_i64(t1, addr, idx, memop); 3588 tcg_gen_ext_i64(t2, val, memop); 3589 gen(t2, t1, t2); 3590 tcg_gen_qemu_st_i64(t2, addr, idx, memop); 3591 3592 tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop); 3593 tcg_temp_free_i64(t1); 3594 tcg_temp_free_i64(t2); 3595 } 3596 3597 static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val, 3598 TCGArg idx, MemOp memop, void * const table[]) 3599 { 3600 memop = tcg_canonicalize_memop(memop, 1, 0); 3601 3602 if ((memop & MO_SIZE) == MO_64) { 3603 #ifdef CONFIG_ATOMIC64 3604 gen_atomic_op_i64 gen; 3605 MemOpIdx oi; 3606 3607 gen = table[memop & (MO_SIZE | MO_BSWAP)]; 3608 tcg_debug_assert(gen != NULL); 3609 3610 oi = make_memop_idx(memop & ~MO_SIGN, idx); 3611 gen(ret, cpu_env, addr, val, tcg_constant_i32(oi)); 3612 #else 3613 gen_helper_exit_atomic(cpu_env); 3614 /* Produce a result, so that we have a well-formed opcode stream 3615 with respect to uses of the result in the (dead) code following. */ 3616 tcg_gen_movi_i64(ret, 0); 3617 #endif /* CONFIG_ATOMIC64 */ 3618 } else { 3619 TCGv_i32 v32 = tcg_temp_new_i32(); 3620 TCGv_i32 r32 = tcg_temp_new_i32(); 3621 3622 tcg_gen_extrl_i64_i32(v32, val); 3623 do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table); 3624 tcg_temp_free_i32(v32); 3625 3626 tcg_gen_extu_i32_i64(ret, r32); 3627 tcg_temp_free_i32(r32); 3628 3629 if (memop & MO_SIGN) { 3630 tcg_gen_ext_i64(ret, ret, memop); 3631 } 3632 } 3633 } 3634 3635 #define GEN_ATOMIC_HELPER(NAME, OP, NEW) \ 3636 static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = { \ 3637 [MO_8] = gen_helper_atomic_##NAME##b, \ 3638 [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le, \ 3639 [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be, \ 3640 [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le, \ 3641 [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be, \ 3642 WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le) \ 3643 WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be) \ 3644 }; \ 3645 void tcg_gen_atomic_##NAME##_i32 \ 3646 (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop) \ 3647 { \ 3648 if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \ 3649 do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \ 3650 } else { \ 3651 do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \ 3652 tcg_gen_##OP##_i32); \ 3653 } \ 3654 } \ 3655 void tcg_gen_atomic_##NAME##_i64 \ 3656 (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop) \ 3657 { \ 3658 if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \ 3659 do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \ 3660 } else { \ 3661 do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \ 3662 tcg_gen_##OP##_i64); \ 3663 } \ 3664 } 3665 3666 GEN_ATOMIC_HELPER(fetch_add, add, 0) 3667 GEN_ATOMIC_HELPER(fetch_and, and, 0) 3668 GEN_ATOMIC_HELPER(fetch_or, or, 0) 3669 GEN_ATOMIC_HELPER(fetch_xor, xor, 0) 3670 GEN_ATOMIC_HELPER(fetch_smin, smin, 0) 3671 GEN_ATOMIC_HELPER(fetch_umin, umin, 0) 3672 GEN_ATOMIC_HELPER(fetch_smax, smax, 0) 3673 GEN_ATOMIC_HELPER(fetch_umax, umax, 0) 3674 3675 GEN_ATOMIC_HELPER(add_fetch, add, 1) 3676 GEN_ATOMIC_HELPER(and_fetch, and, 1) 3677 GEN_ATOMIC_HELPER(or_fetch, or, 1) 3678 GEN_ATOMIC_HELPER(xor_fetch, xor, 1) 3679 GEN_ATOMIC_HELPER(smin_fetch, smin, 1) 3680 GEN_ATOMIC_HELPER(umin_fetch, umin, 1) 3681 GEN_ATOMIC_HELPER(smax_fetch, smax, 1) 3682 GEN_ATOMIC_HELPER(umax_fetch, umax, 1) 3683 3684 static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b) 3685 { 3686 tcg_gen_mov_i32(r, b); 3687 } 3688 3689 static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b) 3690 { 3691 tcg_gen_mov_i64(r, b); 3692 } 3693 3694 GEN_ATOMIC_HELPER(xchg, mov2, 0) 3695 3696 #undef GEN_ATOMIC_HELPER 3697