1951c6300SRichard Henderson /* 2951c6300SRichard Henderson * Tiny Code Generator for QEMU 3951c6300SRichard Henderson * 4951c6300SRichard Henderson * Copyright (c) 2008 Fabrice Bellard 5951c6300SRichard Henderson * 6951c6300SRichard Henderson * Permission is hereby granted, free of charge, to any person obtaining a copy 7951c6300SRichard Henderson * of this software and associated documentation files (the "Software"), to deal 8951c6300SRichard Henderson * in the Software without restriction, including without limitation the rights 9951c6300SRichard Henderson * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10951c6300SRichard Henderson * copies of the Software, and to permit persons to whom the Software is 11951c6300SRichard Henderson * furnished to do so, subject to the following conditions: 12951c6300SRichard Henderson * 13951c6300SRichard Henderson * The above copyright notice and this permission notice shall be included in 14951c6300SRichard Henderson * all copies or substantial portions of the Software. 15951c6300SRichard Henderson * 16951c6300SRichard Henderson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17951c6300SRichard Henderson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18951c6300SRichard Henderson * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19951c6300SRichard Henderson * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20951c6300SRichard Henderson * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21951c6300SRichard Henderson * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22951c6300SRichard Henderson * THE SOFTWARE. 23951c6300SRichard Henderson */ 24951c6300SRichard Henderson 25757e725bSPeter Maydell #include "qemu/osdep.h" 26dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h" 2747f7313dSRichard Henderson #include "tcg/tcg-temp-internal.h" 28ad3d0e4dSRichard Henderson #include "tcg/tcg-op-common.h" 29cac9b0fdSRichard Henderson #include "exec/translation-block.h" 30e6d86bedSEmilio G. Cota #include "exec/plugin-gen.h" 31d56fea79SRichard Henderson #include "tcg-internal.h" 32951c6300SRichard Henderson 33951c6300SRichard Henderson 34b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1) 35951c6300SRichard Henderson { 36d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 1); 3775e8b9b7SRichard Henderson op->args[0] = a1; 38951c6300SRichard Henderson } 39951c6300SRichard Henderson 40b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2) 41951c6300SRichard Henderson { 42d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 2); 4375e8b9b7SRichard Henderson op->args[0] = a1; 4475e8b9b7SRichard Henderson op->args[1] = a2; 45951c6300SRichard Henderson } 46951c6300SRichard Henderson 47b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3) 48951c6300SRichard Henderson { 49d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 3); 5075e8b9b7SRichard Henderson op->args[0] = a1; 5175e8b9b7SRichard Henderson op->args[1] = a2; 5275e8b9b7SRichard Henderson op->args[2] = a3; 53951c6300SRichard Henderson } 54951c6300SRichard Henderson 55b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4) 56951c6300SRichard Henderson { 57d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 4); 5875e8b9b7SRichard Henderson op->args[0] = a1; 5975e8b9b7SRichard Henderson op->args[1] = a2; 6075e8b9b7SRichard Henderson op->args[2] = a3; 6175e8b9b7SRichard Henderson op->args[3] = a4; 62951c6300SRichard Henderson } 63951c6300SRichard Henderson 64b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 65b7e8b17aSRichard Henderson TCGArg a4, TCGArg a5) 66951c6300SRichard Henderson { 67d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 5); 6875e8b9b7SRichard Henderson op->args[0] = a1; 6975e8b9b7SRichard Henderson op->args[1] = a2; 7075e8b9b7SRichard Henderson op->args[2] = a3; 7175e8b9b7SRichard Henderson op->args[3] = a4; 7275e8b9b7SRichard Henderson op->args[4] = a5; 73951c6300SRichard Henderson } 74951c6300SRichard Henderson 75b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 76b7e8b17aSRichard Henderson TCGArg a4, TCGArg a5, TCGArg a6) 77951c6300SRichard Henderson { 78d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 6); 7975e8b9b7SRichard Henderson op->args[0] = a1; 8075e8b9b7SRichard Henderson op->args[1] = a2; 8175e8b9b7SRichard Henderson op->args[2] = a3; 8275e8b9b7SRichard Henderson op->args[3] = a4; 8375e8b9b7SRichard Henderson op->args[4] = a5; 8475e8b9b7SRichard Henderson op->args[5] = a6; 85951c6300SRichard Henderson } 86951c6300SRichard Henderson 87f85b1fc4SRichard Henderson /* Generic ops. */ 88f85b1fc4SRichard Henderson 89f85b1fc4SRichard Henderson static void add_last_as_label_use(TCGLabel *l) 90f85b1fc4SRichard Henderson { 91f85b1fc4SRichard Henderson TCGLabelUse *u = tcg_malloc(sizeof(TCGLabelUse)); 92f85b1fc4SRichard Henderson 93f85b1fc4SRichard Henderson u->op = tcg_last_op(); 94f85b1fc4SRichard Henderson QSIMPLEQ_INSERT_TAIL(&l->branches, u, next); 95f85b1fc4SRichard Henderson } 96f85b1fc4SRichard Henderson 97f85b1fc4SRichard Henderson void tcg_gen_br(TCGLabel *l) 98f85b1fc4SRichard Henderson { 99f85b1fc4SRichard Henderson tcg_gen_op1(INDEX_op_br, label_arg(l)); 100f85b1fc4SRichard Henderson add_last_as_label_use(l); 101f85b1fc4SRichard Henderson } 102f85b1fc4SRichard Henderson 103f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type) 104f65e19bcSPranith Kumar { 105*c914d46dSRichard Henderson #ifdef CONFIG_USER_ONLY 106*c914d46dSRichard Henderson bool parallel = tcg_ctx->gen_tb->cflags & CF_PARALLEL; 107*c914d46dSRichard Henderson #else 108*c914d46dSRichard Henderson /* 109*c914d46dSRichard Henderson * It is tempting to elide the barrier in a uniprocessor context. 110*c914d46dSRichard Henderson * However, even with a single cpu we have i/o threads running in 111*c914d46dSRichard Henderson * parallel, and lack of memory order can result in e.g. virtio 112*c914d46dSRichard Henderson * queue entries being read incorrectly. 113*c914d46dSRichard Henderson */ 114*c914d46dSRichard Henderson bool parallel = true; 115*c914d46dSRichard Henderson #endif 116*c914d46dSRichard Henderson 117*c914d46dSRichard Henderson if (parallel) { 118b7e8b17aSRichard Henderson tcg_gen_op1(INDEX_op_mb, mb_type); 119f65e19bcSPranith Kumar } 120f65e19bcSPranith Kumar } 121f65e19bcSPranith Kumar 122951c6300SRichard Henderson /* 32 bit ops */ 123951c6300SRichard Henderson 12411d11d61SRichard Henderson void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg) 12511d11d61SRichard Henderson { 12611d11d61SRichard Henderson tcg_gen_mov_i32(ret, tcg_constant_i32(arg)); 12711d11d61SRichard Henderson } 12811d11d61SRichard Henderson 129951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 130951c6300SRichard Henderson { 131951c6300SRichard Henderson /* some cases can be optimized here */ 132951c6300SRichard Henderson if (arg2 == 0) { 133951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 134951c6300SRichard Henderson } else { 13511d11d61SRichard Henderson tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2)); 136951c6300SRichard Henderson } 137951c6300SRichard Henderson } 138951c6300SRichard Henderson 139951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2) 140951c6300SRichard Henderson { 141951c6300SRichard Henderson if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) { 142951c6300SRichard Henderson /* Don't recurse with tcg_gen_neg_i32. */ 143951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2); 144951c6300SRichard Henderson } else { 14511d11d61SRichard Henderson tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2); 146951c6300SRichard Henderson } 147951c6300SRichard Henderson } 148951c6300SRichard Henderson 149951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 150951c6300SRichard Henderson { 151951c6300SRichard Henderson /* some cases can be optimized here */ 152951c6300SRichard Henderson if (arg2 == 0) { 153951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 154951c6300SRichard Henderson } else { 15511d11d61SRichard Henderson tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2)); 156951c6300SRichard Henderson } 157951c6300SRichard Henderson } 158951c6300SRichard Henderson 159474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 160951c6300SRichard Henderson { 161951c6300SRichard Henderson /* Some cases can be optimized here. */ 162951c6300SRichard Henderson switch (arg2) { 163951c6300SRichard Henderson case 0: 164951c6300SRichard Henderson tcg_gen_movi_i32(ret, 0); 165951c6300SRichard Henderson return; 166474b2e8fSRichard Henderson case -1: 167951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 168951c6300SRichard Henderson return; 169474b2e8fSRichard Henderson case 0xff: 170951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i32. */ 171951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 172951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1); 173951c6300SRichard Henderson return; 174951c6300SRichard Henderson } 175951c6300SRichard Henderson break; 176474b2e8fSRichard Henderson case 0xffff: 177951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 178951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1); 179951c6300SRichard Henderson return; 180951c6300SRichard Henderson } 181951c6300SRichard Henderson break; 182951c6300SRichard Henderson } 18311d11d61SRichard Henderson 18411d11d61SRichard Henderson tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2)); 185951c6300SRichard Henderson } 186951c6300SRichard Henderson 187951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 188951c6300SRichard Henderson { 189951c6300SRichard Henderson /* Some cases can be optimized here. */ 190951c6300SRichard Henderson if (arg2 == -1) { 191951c6300SRichard Henderson tcg_gen_movi_i32(ret, -1); 192951c6300SRichard Henderson } else if (arg2 == 0) { 193951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 194951c6300SRichard Henderson } else { 19511d11d61SRichard Henderson tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2)); 196951c6300SRichard Henderson } 197951c6300SRichard Henderson } 198951c6300SRichard Henderson 199951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 200951c6300SRichard Henderson { 201951c6300SRichard Henderson /* Some cases can be optimized here. */ 202951c6300SRichard Henderson if (arg2 == 0) { 203951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 204951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) { 205951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i32. */ 206951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1); 207951c6300SRichard Henderson } else { 20811d11d61SRichard Henderson tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2)); 209951c6300SRichard Henderson } 210951c6300SRichard Henderson } 211951c6300SRichard Henderson 212474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 213951c6300SRichard Henderson { 214474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 215951c6300SRichard Henderson if (arg2 == 0) { 216951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 217951c6300SRichard Henderson } else { 21811d11d61SRichard Henderson tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2)); 219951c6300SRichard Henderson } 220951c6300SRichard Henderson } 221951c6300SRichard Henderson 222474b2e8fSRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 223951c6300SRichard Henderson { 224474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 225951c6300SRichard Henderson if (arg2 == 0) { 226951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 227951c6300SRichard Henderson } else { 22811d11d61SRichard Henderson tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2)); 229951c6300SRichard Henderson } 230951c6300SRichard Henderson } 231951c6300SRichard Henderson 232474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 233951c6300SRichard Henderson { 234474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 235951c6300SRichard Henderson if (arg2 == 0) { 236951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 237951c6300SRichard Henderson } else { 23811d11d61SRichard Henderson tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2)); 239951c6300SRichard Henderson } 240951c6300SRichard Henderson } 241951c6300SRichard Henderson 24242a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l) 243951c6300SRichard Henderson { 244951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 24542a268c2SRichard Henderson tcg_gen_br(l); 246951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 24742a268c2SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l)); 248f85b1fc4SRichard Henderson add_last_as_label_use(l); 249951c6300SRichard Henderson } 250951c6300SRichard Henderson } 251951c6300SRichard Henderson 25242a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l) 253951c6300SRichard Henderson { 25437ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 25537ed3bf1SRichard Henderson tcg_gen_br(l); 25637ed3bf1SRichard Henderson } else if (cond != TCG_COND_NEVER) { 25711d11d61SRichard Henderson tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l); 258951c6300SRichard Henderson } 25937ed3bf1SRichard Henderson } 260951c6300SRichard Henderson 261951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret, 262951c6300SRichard Henderson TCGv_i32 arg1, TCGv_i32 arg2) 263951c6300SRichard Henderson { 264951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 265951c6300SRichard Henderson tcg_gen_movi_i32(ret, 1); 266951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 267951c6300SRichard Henderson tcg_gen_movi_i32(ret, 0); 268951c6300SRichard Henderson } else { 269951c6300SRichard Henderson tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); 270951c6300SRichard Henderson } 271951c6300SRichard Henderson } 272951c6300SRichard Henderson 273951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, 274951c6300SRichard Henderson TCGv_i32 arg1, int32_t arg2) 275951c6300SRichard Henderson { 27611d11d61SRichard Henderson tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2)); 277951c6300SRichard Henderson } 278951c6300SRichard Henderson 279951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 280951c6300SRichard Henderson { 281b2e3ae94SRichard Henderson if (arg2 == 0) { 282b2e3ae94SRichard Henderson tcg_gen_movi_i32(ret, 0); 283b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 284b2e3ae94SRichard Henderson tcg_gen_shli_i32(ret, arg1, ctz32(arg2)); 285b2e3ae94SRichard Henderson } else { 28611d11d61SRichard Henderson tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2)); 287951c6300SRichard Henderson } 288b2e3ae94SRichard Henderson } 289951c6300SRichard Henderson 290951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 291951c6300SRichard Henderson { 292951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 293951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2); 294951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 2955dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 296951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 297951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2); 298951c6300SRichard Henderson tcg_temp_free_i32(t0); 299951c6300SRichard Henderson } else { 300951c6300SRichard Henderson gen_helper_div_i32(ret, arg1, arg2); 301951c6300SRichard Henderson } 302951c6300SRichard Henderson } 303951c6300SRichard Henderson 304951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 305951c6300SRichard Henderson { 306951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 307951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2); 308951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 3095dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 310951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2); 311951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 312951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 313951c6300SRichard Henderson tcg_temp_free_i32(t0); 314951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3155dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 316951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 317951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2); 318951c6300SRichard Henderson tcg_temp_free_i32(t0); 319951c6300SRichard Henderson } else { 320951c6300SRichard Henderson gen_helper_rem_i32(ret, arg1, arg2); 321951c6300SRichard Henderson } 322951c6300SRichard Henderson } 323951c6300SRichard Henderson 324951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 325951c6300SRichard Henderson { 326951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 327951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2); 328951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3295dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 330951c6300SRichard Henderson tcg_gen_movi_i32(t0, 0); 331951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2); 332951c6300SRichard Henderson tcg_temp_free_i32(t0); 333951c6300SRichard Henderson } else { 334951c6300SRichard Henderson gen_helper_divu_i32(ret, arg1, arg2); 335951c6300SRichard Henderson } 336951c6300SRichard Henderson } 337951c6300SRichard Henderson 338951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 339951c6300SRichard Henderson { 340951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 341951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); 342951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 3435dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 344951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2); 345951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 346951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 347951c6300SRichard Henderson tcg_temp_free_i32(t0); 348951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3495dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 350951c6300SRichard Henderson tcg_gen_movi_i32(t0, 0); 351951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); 352951c6300SRichard Henderson tcg_temp_free_i32(t0); 353951c6300SRichard Henderson } else { 354951c6300SRichard Henderson gen_helper_remu_i32(ret, arg1, arg2); 355951c6300SRichard Henderson } 356951c6300SRichard Henderson } 357951c6300SRichard Henderson 358951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 359951c6300SRichard Henderson { 360951c6300SRichard Henderson if (TCG_TARGET_HAS_andc_i32) { 361951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2); 362951c6300SRichard Henderson } else { 3635dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 364951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 365951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, t0); 366951c6300SRichard Henderson tcg_temp_free_i32(t0); 367951c6300SRichard Henderson } 368951c6300SRichard Henderson } 369951c6300SRichard Henderson 370951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 371951c6300SRichard Henderson { 372951c6300SRichard Henderson if (TCG_TARGET_HAS_eqv_i32) { 373951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2); 374951c6300SRichard Henderson } else { 375951c6300SRichard Henderson tcg_gen_xor_i32(ret, arg1, arg2); 376951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 377951c6300SRichard Henderson } 378951c6300SRichard Henderson } 379951c6300SRichard Henderson 380951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 381951c6300SRichard Henderson { 382951c6300SRichard Henderson if (TCG_TARGET_HAS_nand_i32) { 383951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2); 384951c6300SRichard Henderson } else { 385951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, arg2); 386951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 387951c6300SRichard Henderson } 388951c6300SRichard Henderson } 389951c6300SRichard Henderson 390951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 391951c6300SRichard Henderson { 392951c6300SRichard Henderson if (TCG_TARGET_HAS_nor_i32) { 393951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2); 394951c6300SRichard Henderson } else { 395951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, arg2); 396951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 397951c6300SRichard Henderson } 398951c6300SRichard Henderson } 399951c6300SRichard Henderson 400951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 401951c6300SRichard Henderson { 402951c6300SRichard Henderson if (TCG_TARGET_HAS_orc_i32) { 403951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2); 404951c6300SRichard Henderson } else { 4055dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 406951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 407951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, t0); 408951c6300SRichard Henderson tcg_temp_free_i32(t0); 409951c6300SRichard Henderson } 410951c6300SRichard Henderson } 411951c6300SRichard Henderson 4120e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 4130e28d006SRichard Henderson { 4140e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 4150e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2); 4160e28d006SRichard Henderson } else if (TCG_TARGET_HAS_clz_i64) { 4175dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 4185dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 4190e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 4200e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 4210e28d006SRichard Henderson tcg_gen_addi_i64(t2, t2, 32); 4220e28d006SRichard Henderson tcg_gen_clz_i64(t1, t1, t2); 4230e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 4240e28d006SRichard Henderson tcg_temp_free_i64(t1); 4250e28d006SRichard Henderson tcg_temp_free_i64(t2); 4260e28d006SRichard Henderson tcg_gen_subi_i32(ret, ret, 32); 4270e28d006SRichard Henderson } else { 4280e28d006SRichard Henderson gen_helper_clz_i32(ret, arg1, arg2); 4290e28d006SRichard Henderson } 4300e28d006SRichard Henderson } 4310e28d006SRichard Henderson 4320e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 4330e28d006SRichard Henderson { 43411d11d61SRichard Henderson tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2)); 4350e28d006SRichard Henderson } 4360e28d006SRichard Henderson 4370e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 4380e28d006SRichard Henderson { 4390e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i32) { 4400e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2); 4410e28d006SRichard Henderson } else if (TCG_TARGET_HAS_ctz_i64) { 4425dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 4435dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 4440e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 4450e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 4460e28d006SRichard Henderson tcg_gen_ctz_i64(t1, t1, t2); 4470e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 4480e28d006SRichard Henderson tcg_temp_free_i64(t1); 4490e28d006SRichard Henderson tcg_temp_free_i64(t2); 45014e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i32 45114e99210SRichard Henderson || TCG_TARGET_HAS_ctpop_i64 45214e99210SRichard Henderson || TCG_TARGET_HAS_clz_i32 45314e99210SRichard Henderson || TCG_TARGET_HAS_clz_i64) { 4545dd48602SRichard Henderson TCGv_i32 z, t = tcg_temp_ebb_new_i32(); 45514e99210SRichard Henderson 45614e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) { 45714e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 45814e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 45914e99210SRichard Henderson tcg_gen_ctpop_i32(t, t); 46014e99210SRichard Henderson } else { 46114e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 32, don't fight it. */ 46214e99210SRichard Henderson tcg_gen_neg_i32(t, arg1); 46314e99210SRichard Henderson tcg_gen_and_i32(t, t, arg1); 46414e99210SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 46514e99210SRichard Henderson tcg_gen_xori_i32(t, t, 31); 46614e99210SRichard Henderson } 46711d11d61SRichard Henderson z = tcg_constant_i32(0); 46814e99210SRichard Henderson tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t); 46914e99210SRichard Henderson tcg_temp_free_i32(t); 4700e28d006SRichard Henderson } else { 4710e28d006SRichard Henderson gen_helper_ctz_i32(ret, arg1, arg2); 4720e28d006SRichard Henderson } 4730e28d006SRichard Henderson } 4740e28d006SRichard Henderson 4750e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 4760e28d006SRichard Henderson { 47714e99210SRichard Henderson if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) { 47814e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 4795dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 48014e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 48114e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 48214e99210SRichard Henderson tcg_gen_ctpop_i32(ret, t); 48314e99210SRichard Henderson tcg_temp_free_i32(t); 48414e99210SRichard Henderson } else { 48511d11d61SRichard Henderson tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2)); 4860e28d006SRichard Henderson } 48714e99210SRichard Henderson } 4880e28d006SRichard Henderson 489086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg) 490086920c2SRichard Henderson { 491086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 4925dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 493086920c2SRichard Henderson tcg_gen_sari_i32(t, arg, 31); 494086920c2SRichard Henderson tcg_gen_xor_i32(t, t, arg); 495086920c2SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 496086920c2SRichard Henderson tcg_gen_subi_i32(ret, t, 1); 497086920c2SRichard Henderson tcg_temp_free_i32(t); 498086920c2SRichard Henderson } else { 499086920c2SRichard Henderson gen_helper_clrsb_i32(ret, arg); 500086920c2SRichard Henderson } 501086920c2SRichard Henderson } 502086920c2SRichard Henderson 503a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1) 504a768e4e9SRichard Henderson { 505a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32) { 506a768e4e9SRichard Henderson tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1); 507a768e4e9SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64) { 5085dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 509a768e4e9SRichard Henderson tcg_gen_extu_i32_i64(t, arg1); 510a768e4e9SRichard Henderson tcg_gen_ctpop_i64(t, t); 511a768e4e9SRichard Henderson tcg_gen_extrl_i64_i32(ret, t); 512a768e4e9SRichard Henderson tcg_temp_free_i64(t); 513a768e4e9SRichard Henderson } else { 514a768e4e9SRichard Henderson gen_helper_ctpop_i32(ret, arg1); 515a768e4e9SRichard Henderson } 516a768e4e9SRichard Henderson } 517a768e4e9SRichard Henderson 518951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 519951c6300SRichard Henderson { 520951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 521951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2); 522951c6300SRichard Henderson } else { 523951c6300SRichard Henderson TCGv_i32 t0, t1; 524951c6300SRichard Henderson 5255dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 5265dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 527951c6300SRichard Henderson tcg_gen_shl_i32(t0, arg1, arg2); 528951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 529951c6300SRichard Henderson tcg_gen_shr_i32(t1, arg1, t1); 530951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 531951c6300SRichard Henderson tcg_temp_free_i32(t0); 532951c6300SRichard Henderson tcg_temp_free_i32(t1); 533951c6300SRichard Henderson } 534951c6300SRichard Henderson } 535951c6300SRichard Henderson 53607dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 537951c6300SRichard Henderson { 53807dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 539951c6300SRichard Henderson /* some cases can be optimized here */ 540951c6300SRichard Henderson if (arg2 == 0) { 541951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 542951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i32) { 54311d11d61SRichard Henderson tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2)); 544951c6300SRichard Henderson } else { 545951c6300SRichard Henderson TCGv_i32 t0, t1; 5465dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 5475dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 548951c6300SRichard Henderson tcg_gen_shli_i32(t0, arg1, arg2); 549951c6300SRichard Henderson tcg_gen_shri_i32(t1, arg1, 32 - arg2); 550951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 551951c6300SRichard Henderson tcg_temp_free_i32(t0); 552951c6300SRichard Henderson tcg_temp_free_i32(t1); 553951c6300SRichard Henderson } 554951c6300SRichard Henderson } 555951c6300SRichard Henderson 556951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 557951c6300SRichard Henderson { 558951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 559951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2); 560951c6300SRichard Henderson } else { 561951c6300SRichard Henderson TCGv_i32 t0, t1; 562951c6300SRichard Henderson 5635dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 5645dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 565951c6300SRichard Henderson tcg_gen_shr_i32(t0, arg1, arg2); 566951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 567951c6300SRichard Henderson tcg_gen_shl_i32(t1, arg1, t1); 568951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 569951c6300SRichard Henderson tcg_temp_free_i32(t0); 570951c6300SRichard Henderson tcg_temp_free_i32(t1); 571951c6300SRichard Henderson } 572951c6300SRichard Henderson } 573951c6300SRichard Henderson 57407dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 575951c6300SRichard Henderson { 57607dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 577951c6300SRichard Henderson /* some cases can be optimized here */ 578951c6300SRichard Henderson if (arg2 == 0) { 579951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 580951c6300SRichard Henderson } else { 581951c6300SRichard Henderson tcg_gen_rotli_i32(ret, arg1, 32 - arg2); 582951c6300SRichard Henderson } 583951c6300SRichard Henderson } 584951c6300SRichard Henderson 585951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, 586951c6300SRichard Henderson unsigned int ofs, unsigned int len) 587951c6300SRichard Henderson { 588951c6300SRichard Henderson uint32_t mask; 589951c6300SRichard Henderson TCGv_i32 t1; 590951c6300SRichard Henderson 591951c6300SRichard Henderson tcg_debug_assert(ofs < 32); 5920d0d309dSRichard Henderson tcg_debug_assert(len > 0); 593951c6300SRichard Henderson tcg_debug_assert(len <= 32); 594951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 32); 595951c6300SRichard Henderson 5960d0d309dSRichard Henderson if (len == 32) { 597951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg2); 598951c6300SRichard Henderson return; 599951c6300SRichard Henderson } 600951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) { 601951c6300SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); 602951c6300SRichard Henderson return; 603951c6300SRichard Henderson } 604951c6300SRichard Henderson 6055dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 606951c6300SRichard Henderson 607b0a60567SRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 608b0a60567SRichard Henderson if (ofs + len == 32) { 609b0a60567SRichard Henderson tcg_gen_shli_i32(t1, arg1, len); 610b0a60567SRichard Henderson tcg_gen_extract2_i32(ret, t1, arg2, len); 611b0a60567SRichard Henderson goto done; 612b0a60567SRichard Henderson } 613b0a60567SRichard Henderson if (ofs == 0) { 614b0a60567SRichard Henderson tcg_gen_extract2_i32(ret, arg1, arg2, len); 615b0a60567SRichard Henderson tcg_gen_rotli_i32(ret, ret, len); 616b0a60567SRichard Henderson goto done; 617b0a60567SRichard Henderson } 618b0a60567SRichard Henderson } 619b0a60567SRichard Henderson 620b0a60567SRichard Henderson mask = (1u << len) - 1; 621951c6300SRichard Henderson if (ofs + len < 32) { 622951c6300SRichard Henderson tcg_gen_andi_i32(t1, arg2, mask); 623951c6300SRichard Henderson tcg_gen_shli_i32(t1, t1, ofs); 624951c6300SRichard Henderson } else { 625951c6300SRichard Henderson tcg_gen_shli_i32(t1, arg2, ofs); 626951c6300SRichard Henderson } 627951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg1, ~(mask << ofs)); 628951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 629b0a60567SRichard Henderson done: 630951c6300SRichard Henderson tcg_temp_free_i32(t1); 631951c6300SRichard Henderson } 632951c6300SRichard Henderson 63307cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, 63407cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 63507cc68d5SRichard Henderson { 63607cc68d5SRichard Henderson tcg_debug_assert(ofs < 32); 63707cc68d5SRichard Henderson tcg_debug_assert(len > 0); 63807cc68d5SRichard Henderson tcg_debug_assert(len <= 32); 63907cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 32); 64007cc68d5SRichard Henderson 64107cc68d5SRichard Henderson if (ofs + len == 32) { 64207cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 64307cc68d5SRichard Henderson } else if (ofs == 0) { 64407cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 64507cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i32 64607cc68d5SRichard Henderson && TCG_TARGET_deposit_i32_valid(ofs, len)) { 64711d11d61SRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 64807cc68d5SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); 64907cc68d5SRichard Henderson } else { 65007cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 65107cc68d5SRichard Henderson which allows ARG to stay live. */ 65207cc68d5SRichard Henderson switch (len) { 65307cc68d5SRichard Henderson case 16: 65407cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 65507cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 65607cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 65707cc68d5SRichard Henderson return; 65807cc68d5SRichard Henderson } 65907cc68d5SRichard Henderson break; 66007cc68d5SRichard Henderson case 8: 66107cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 66207cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 66307cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 66407cc68d5SRichard Henderson return; 66507cc68d5SRichard Henderson } 66607cc68d5SRichard Henderson break; 66707cc68d5SRichard Henderson } 66807cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 66907cc68d5SRichard Henderson switch (ofs + len) { 67007cc68d5SRichard Henderson case 16: 67107cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 67207cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 67307cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, ret); 67407cc68d5SRichard Henderson return; 67507cc68d5SRichard Henderson } 67607cc68d5SRichard Henderson break; 67707cc68d5SRichard Henderson case 8: 67807cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 67907cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 68007cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, ret); 68107cc68d5SRichard Henderson return; 68207cc68d5SRichard Henderson } 68307cc68d5SRichard Henderson break; 68407cc68d5SRichard Henderson } 68507cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 68607cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 68707cc68d5SRichard Henderson } 68807cc68d5SRichard Henderson } 68907cc68d5SRichard Henderson 6907ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, 6917ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 6927ec8bab3SRichard Henderson { 6937ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 6947ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 6957ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 6967ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 6977ec8bab3SRichard Henderson 6987ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 6997ec8bab3SRichard Henderson if (ofs + len == 32) { 7007ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, 32 - len); 7017ec8bab3SRichard Henderson return; 7027ec8bab3SRichard Henderson } 7037ec8bab3SRichard Henderson if (ofs == 0) { 7047ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 7057ec8bab3SRichard Henderson return; 7067ec8bab3SRichard Henderson } 7077ec8bab3SRichard Henderson 7087ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i32 7097ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 7107ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len); 7117ec8bab3SRichard Henderson return; 7127ec8bab3SRichard Henderson } 7137ec8bab3SRichard Henderson 7147ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 7157ec8bab3SRichard Henderson switch (ofs + len) { 7167ec8bab3SRichard Henderson case 16: 7177ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 7187ec8bab3SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 7197ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 7207ec8bab3SRichard Henderson return; 7217ec8bab3SRichard Henderson } 7227ec8bab3SRichard Henderson break; 7237ec8bab3SRichard Henderson case 8: 7247ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 7257ec8bab3SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 7267ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 7277ec8bab3SRichard Henderson return; 7287ec8bab3SRichard Henderson } 7297ec8bab3SRichard Henderson break; 7307ec8bab3SRichard Henderson } 7317ec8bab3SRichard Henderson 7327ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 7337ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special case of 16, 7347ec8bab3SRichard Henderson so that we get ext8u, ext16u. */ 7357ec8bab3SRichard Henderson switch (len) { 7367ec8bab3SRichard Henderson case 1 ... 8: case 16: 7377ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 7387ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, ret, (1u << len) - 1); 7397ec8bab3SRichard Henderson break; 7407ec8bab3SRichard Henderson default: 7417ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 7427ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, 32 - len); 7437ec8bab3SRichard Henderson break; 7447ec8bab3SRichard Henderson } 7457ec8bab3SRichard Henderson } 7467ec8bab3SRichard Henderson 7477ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg, 7487ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 7497ec8bab3SRichard Henderson { 7507ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 7517ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 7527ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 7537ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 7547ec8bab3SRichard Henderson 7557ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 7567ec8bab3SRichard Henderson if (ofs + len == 32) { 7577ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, arg, 32 - len); 7587ec8bab3SRichard Henderson return; 7597ec8bab3SRichard Henderson } 7607ec8bab3SRichard Henderson if (ofs == 0) { 7617ec8bab3SRichard Henderson switch (len) { 7627ec8bab3SRichard Henderson case 16: 7637ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 7647ec8bab3SRichard Henderson return; 7657ec8bab3SRichard Henderson case 8: 7667ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 7677ec8bab3SRichard Henderson return; 7687ec8bab3SRichard Henderson } 7697ec8bab3SRichard Henderson } 7707ec8bab3SRichard Henderson 7717ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i32 7727ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 7737ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); 7747ec8bab3SRichard Henderson return; 7757ec8bab3SRichard Henderson } 7767ec8bab3SRichard Henderson 7777ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 7787ec8bab3SRichard Henderson switch (ofs + len) { 7797ec8bab3SRichard Henderson case 16: 7807ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 7817ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 7827ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 7837ec8bab3SRichard Henderson return; 7847ec8bab3SRichard Henderson } 7857ec8bab3SRichard Henderson break; 7867ec8bab3SRichard Henderson case 8: 7877ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 7887ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 7897ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 7907ec8bab3SRichard Henderson return; 7917ec8bab3SRichard Henderson } 7927ec8bab3SRichard Henderson break; 7937ec8bab3SRichard Henderson } 7947ec8bab3SRichard Henderson switch (len) { 7957ec8bab3SRichard Henderson case 16: 7967ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 7977ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 7987ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, ret); 7997ec8bab3SRichard Henderson return; 8007ec8bab3SRichard Henderson } 8017ec8bab3SRichard Henderson break; 8027ec8bab3SRichard Henderson case 8: 8037ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 8047ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 8057ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, ret); 8067ec8bab3SRichard Henderson return; 8077ec8bab3SRichard Henderson } 8087ec8bab3SRichard Henderson break; 8097ec8bab3SRichard Henderson } 8107ec8bab3SRichard Henderson 8117ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 8127ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, 32 - len); 8137ec8bab3SRichard Henderson } 8147ec8bab3SRichard Henderson 8152089fcc9SDavid Hildenbrand /* 8162089fcc9SDavid Hildenbrand * Extract 32-bits from a 64-bit input, ah:al, starting from ofs. 8172089fcc9SDavid Hildenbrand * Unlike tcg_gen_extract_i32 above, len is fixed at 32. 8182089fcc9SDavid Hildenbrand */ 8192089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah, 8202089fcc9SDavid Hildenbrand unsigned int ofs) 8212089fcc9SDavid Hildenbrand { 8222089fcc9SDavid Hildenbrand tcg_debug_assert(ofs <= 32); 8232089fcc9SDavid Hildenbrand if (ofs == 0) { 8242089fcc9SDavid Hildenbrand tcg_gen_mov_i32(ret, al); 8252089fcc9SDavid Hildenbrand } else if (ofs == 32) { 8262089fcc9SDavid Hildenbrand tcg_gen_mov_i32(ret, ah); 8272089fcc9SDavid Hildenbrand } else if (al == ah) { 8282089fcc9SDavid Hildenbrand tcg_gen_rotri_i32(ret, al, ofs); 829fce1296fSRichard Henderson } else if (TCG_TARGET_HAS_extract2_i32) { 830fce1296fSRichard Henderson tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs); 8312089fcc9SDavid Hildenbrand } else { 8325dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 8332089fcc9SDavid Hildenbrand tcg_gen_shri_i32(t0, al, ofs); 8342089fcc9SDavid Hildenbrand tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs); 8352089fcc9SDavid Hildenbrand tcg_temp_free_i32(t0); 8362089fcc9SDavid Hildenbrand } 8372089fcc9SDavid Hildenbrand } 8382089fcc9SDavid Hildenbrand 839951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, 840951c6300SRichard Henderson TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) 841951c6300SRichard Henderson { 84237ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 84337ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v1); 84437ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 84537ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v2); 84637ed3bf1SRichard Henderson } else if (TCG_TARGET_HAS_movcond_i32) { 847951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond); 848951c6300SRichard Henderson } else { 8495dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 8505dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 851951c6300SRichard Henderson tcg_gen_setcond_i32(cond, t0, c1, c2); 852951c6300SRichard Henderson tcg_gen_neg_i32(t0, t0); 853951c6300SRichard Henderson tcg_gen_and_i32(t1, v1, t0); 854951c6300SRichard Henderson tcg_gen_andc_i32(ret, v2, t0); 855951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 856951c6300SRichard Henderson tcg_temp_free_i32(t0); 857951c6300SRichard Henderson tcg_temp_free_i32(t1); 858951c6300SRichard Henderson } 859951c6300SRichard Henderson } 860951c6300SRichard Henderson 861951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 862951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 863951c6300SRichard Henderson { 864951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i32) { 865951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh); 866951c6300SRichard Henderson } else { 8675dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 8685dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 869951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 870951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 871951c6300SRichard Henderson tcg_gen_add_i64(t0, t0, t1); 872951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 873951c6300SRichard Henderson tcg_temp_free_i64(t0); 874951c6300SRichard Henderson tcg_temp_free_i64(t1); 875951c6300SRichard Henderson } 876951c6300SRichard Henderson } 877951c6300SRichard Henderson 878951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 879951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 880951c6300SRichard Henderson { 881951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i32) { 882951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh); 883951c6300SRichard Henderson } else { 8845dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 8855dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 886951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 887951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 888951c6300SRichard Henderson tcg_gen_sub_i64(t0, t0, t1); 889951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 890951c6300SRichard Henderson tcg_temp_free_i64(t0); 891951c6300SRichard Henderson tcg_temp_free_i64(t1); 892951c6300SRichard Henderson } 893951c6300SRichard Henderson } 894951c6300SRichard Henderson 895951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 896951c6300SRichard Henderson { 897951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i32) { 898951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); 899951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i32) { 9005dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 901951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 902951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2); 903951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 904951c6300SRichard Henderson tcg_temp_free_i32(t); 9059fd86b51SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 9065dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 9075dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 908951c6300SRichard Henderson tcg_gen_extu_i32_i64(t0, arg1); 909951c6300SRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 910951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 911951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 912951c6300SRichard Henderson tcg_temp_free_i64(t0); 913951c6300SRichard Henderson tcg_temp_free_i64(t1); 9149fd86b51SRichard Henderson } else { 9159fd86b51SRichard Henderson qemu_build_not_reached(); 916951c6300SRichard Henderson } 917951c6300SRichard Henderson } 918951c6300SRichard Henderson 919951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 920951c6300SRichard Henderson { 921951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i32) { 922951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); 923951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i32) { 9245dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 925951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 926951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2); 927951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 928951c6300SRichard Henderson tcg_temp_free_i32(t); 929951c6300SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 9305dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 9315dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 9325dd48602SRichard Henderson TCGv_i32 t2 = tcg_temp_ebb_new_i32(); 9335dd48602SRichard Henderson TCGv_i32 t3 = tcg_temp_ebb_new_i32(); 934951c6300SRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 935951c6300SRichard Henderson /* Adjust for negative inputs. */ 936951c6300SRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 937951c6300SRichard Henderson tcg_gen_sari_i32(t3, arg2, 31); 938951c6300SRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 939951c6300SRichard Henderson tcg_gen_and_i32(t3, t3, arg1); 940951c6300SRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 941951c6300SRichard Henderson tcg_gen_sub_i32(rh, rh, t3); 942951c6300SRichard Henderson tcg_gen_mov_i32(rl, t0); 943951c6300SRichard Henderson tcg_temp_free_i32(t0); 944951c6300SRichard Henderson tcg_temp_free_i32(t1); 945951c6300SRichard Henderson tcg_temp_free_i32(t2); 946951c6300SRichard Henderson tcg_temp_free_i32(t3); 947951c6300SRichard Henderson } else { 9485dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 9495dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 950951c6300SRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 951951c6300SRichard Henderson tcg_gen_ext_i32_i64(t1, arg2); 952951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 953951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 954951c6300SRichard Henderson tcg_temp_free_i64(t0); 955951c6300SRichard Henderson tcg_temp_free_i64(t1); 956951c6300SRichard Henderson } 957951c6300SRichard Henderson } 958951c6300SRichard Henderson 9595087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 9605087abfbSRichard Henderson { 9615087abfbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 9625dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 9635dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 9645dd48602SRichard Henderson TCGv_i32 t2 = tcg_temp_ebb_new_i32(); 9655087abfbSRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 9665087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 9675087abfbSRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 9685087abfbSRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 9695087abfbSRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 9705087abfbSRichard Henderson tcg_gen_mov_i32(rl, t0); 9715087abfbSRichard Henderson tcg_temp_free_i32(t0); 9725087abfbSRichard Henderson tcg_temp_free_i32(t1); 9735087abfbSRichard Henderson tcg_temp_free_i32(t2); 9745087abfbSRichard Henderson } else { 9755dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 9765dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 9775087abfbSRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 9785087abfbSRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 9795087abfbSRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 9805087abfbSRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 9815087abfbSRichard Henderson tcg_temp_free_i64(t0); 9825087abfbSRichard Henderson tcg_temp_free_i64(t1); 9835087abfbSRichard Henderson } 9845087abfbSRichard Henderson } 9855087abfbSRichard Henderson 986951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg) 987951c6300SRichard Henderson { 988951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 989951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg); 990951c6300SRichard Henderson } else { 991951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 24); 992951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 24); 993951c6300SRichard Henderson } 994951c6300SRichard Henderson } 995951c6300SRichard Henderson 996951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg) 997951c6300SRichard Henderson { 998951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 999951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg); 1000951c6300SRichard Henderson } else { 1001951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 16); 1002951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 16); 1003951c6300SRichard Henderson } 1004951c6300SRichard Henderson } 1005951c6300SRichard Henderson 1006951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg) 1007951c6300SRichard Henderson { 1008951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 1009951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg); 1010951c6300SRichard Henderson } else { 1011951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffu); 1012951c6300SRichard Henderson } 1013951c6300SRichard Henderson } 1014951c6300SRichard Henderson 1015951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg) 1016951c6300SRichard Henderson { 1017951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 1018951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg); 1019951c6300SRichard Henderson } else { 1020951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffffu); 1021951c6300SRichard Henderson } 1022951c6300SRichard Henderson } 1023951c6300SRichard Henderson 10242b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags) 1025951c6300SRichard Henderson { 10262b836c2aSRichard Henderson /* Only one extension flag may be present. */ 10272b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 10282b836c2aSRichard Henderson 1029951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap16_i32) { 10302b836c2aSRichard Henderson tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags); 1031951c6300SRichard Henderson } else { 10325dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 10335dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 1034951c6300SRichard Henderson 10352b836c2aSRichard Henderson tcg_gen_shri_i32(t0, arg, 8); 10362b836c2aSRichard Henderson if (!(flags & TCG_BSWAP_IZ)) { 10372b836c2aSRichard Henderson tcg_gen_ext8u_i32(t0, t0); 10382b836c2aSRichard Henderson } 10392b836c2aSRichard Henderson 10402b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 10412b836c2aSRichard Henderson tcg_gen_shli_i32(t1, arg, 24); 10422b836c2aSRichard Henderson tcg_gen_sari_i32(t1, t1, 16); 10432b836c2aSRichard Henderson } else if (flags & TCG_BSWAP_OZ) { 10442b836c2aSRichard Henderson tcg_gen_ext8u_i32(t1, arg); 10452b836c2aSRichard Henderson tcg_gen_shli_i32(t1, t1, 8); 10462b836c2aSRichard Henderson } else { 10472b836c2aSRichard Henderson tcg_gen_shli_i32(t1, arg, 8); 10482b836c2aSRichard Henderson } 10492b836c2aSRichard Henderson 10502b836c2aSRichard Henderson tcg_gen_or_i32(ret, t0, t1); 1051951c6300SRichard Henderson tcg_temp_free_i32(t0); 10522b836c2aSRichard Henderson tcg_temp_free_i32(t1); 1053951c6300SRichard Henderson } 1054951c6300SRichard Henderson } 1055951c6300SRichard Henderson 1056951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg) 1057951c6300SRichard Henderson { 1058951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap32_i32) { 1059587195bdSRichard Henderson tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0); 1060951c6300SRichard Henderson } else { 10615dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 10625dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 106311d11d61SRichard Henderson TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff); 1064951c6300SRichard Henderson 1065a686dc71SRichard Henderson /* arg = abcd */ 1066a686dc71SRichard Henderson tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */ 1067a686dc71SRichard Henderson tcg_gen_and_i32(t1, arg, t2); /* t1 = .b.d */ 1068a686dc71SRichard Henderson tcg_gen_and_i32(t0, t0, t2); /* t0 = .a.c */ 1069a686dc71SRichard Henderson tcg_gen_shli_i32(t1, t1, 8); /* t1 = b.d. */ 1070a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = badc */ 1071951c6300SRichard Henderson 1072a686dc71SRichard Henderson tcg_gen_shri_i32(t0, ret, 16); /* t0 = ..ba */ 1073a686dc71SRichard Henderson tcg_gen_shli_i32(t1, ret, 16); /* t1 = dc.. */ 1074a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = dcba */ 1075951c6300SRichard Henderson 1076951c6300SRichard Henderson tcg_temp_free_i32(t0); 1077951c6300SRichard Henderson tcg_temp_free_i32(t1); 1078951c6300SRichard Henderson } 1079951c6300SRichard Henderson } 1080951c6300SRichard Henderson 108146be8425SRichard Henderson void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg) 108246be8425SRichard Henderson { 108346be8425SRichard Henderson /* Swapping 2 16-bit elements is a rotate. */ 108446be8425SRichard Henderson tcg_gen_rotli_i32(ret, arg, 16); 108546be8425SRichard Henderson } 108646be8425SRichard Henderson 1087b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1088b87fb8cdSRichard Henderson { 1089b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); 1090b87fb8cdSRichard Henderson } 1091b87fb8cdSRichard Henderson 1092b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1093b87fb8cdSRichard Henderson { 1094b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); 1095b87fb8cdSRichard Henderson } 1096b87fb8cdSRichard Henderson 1097b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1098b87fb8cdSRichard Henderson { 1099b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); 1100b87fb8cdSRichard Henderson } 1101b87fb8cdSRichard Henderson 1102b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1103b87fb8cdSRichard Henderson { 1104b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); 1105b87fb8cdSRichard Henderson } 1106b87fb8cdSRichard Henderson 1107ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a) 1108ff1f11f7SRichard Henderson { 11095dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 1110ff1f11f7SRichard Henderson 1111ff1f11f7SRichard Henderson tcg_gen_sari_i32(t, a, 31); 1112ff1f11f7SRichard Henderson tcg_gen_xor_i32(ret, a, t); 1113ff1f11f7SRichard Henderson tcg_gen_sub_i32(ret, ret, t); 1114ff1f11f7SRichard Henderson tcg_temp_free_i32(t); 1115ff1f11f7SRichard Henderson } 1116ff1f11f7SRichard Henderson 1117951c6300SRichard Henderson /* 64-bit ops */ 1118951c6300SRichard Henderson 1119951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32 1120951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64. */ 1121951c6300SRichard Henderson 1122951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg) 1123951c6300SRichard Henderson { 1124951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_LOW(arg)); 1125951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_HIGH(arg)); 1126951c6300SRichard Henderson } 1127951c6300SRichard Henderson 1128951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg) 1129951c6300SRichard Henderson { 113011d11d61SRichard Henderson TCGTemp *ts = tcgv_i64_temp(arg); 113111d11d61SRichard Henderson 113211d11d61SRichard Henderson /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */ 113311d11d61SRichard Henderson if (ts->kind == TEMP_CONST) { 113411d11d61SRichard Henderson tcg_gen_movi_i64(ret, ts->val); 113511d11d61SRichard Henderson } else { 1136951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1137951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 1138951c6300SRichard Henderson } 113911d11d61SRichard Henderson } 1140951c6300SRichard Henderson 1141951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 1142951c6300SRichard Henderson { 1143951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), arg); 1144951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32); 1145951c6300SRichard Henderson } 1146951c6300SRichard Henderson 1147951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1148951c6300SRichard Henderson { 1149951c6300SRichard Henderson tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset); 1150951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1151951c6300SRichard Henderson } 1152951c6300SRichard Henderson 1153951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1154951c6300SRichard Henderson { 1155951c6300SRichard Henderson tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset); 11563ff91d7eSJoseph Myers tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1157951c6300SRichard Henderson } 1158951c6300SRichard Henderson 1159951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1160951c6300SRichard Henderson { 1161951c6300SRichard Henderson tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset); 1162951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1163951c6300SRichard Henderson } 1164951c6300SRichard Henderson 1165951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1166951c6300SRichard Henderson { 1167951c6300SRichard Henderson tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset); 1168951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1169951c6300SRichard Henderson } 1170951c6300SRichard Henderson 1171951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1172951c6300SRichard Henderson { 1173951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1174951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1175951c6300SRichard Henderson } 1176951c6300SRichard Henderson 1177951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1178951c6300SRichard Henderson { 1179951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1180951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1181951c6300SRichard Henderson } 1182951c6300SRichard Henderson 1183951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1184951c6300SRichard Henderson { 1185951c6300SRichard Henderson /* Since arg2 and ret have different types, 1186951c6300SRichard Henderson they cannot be the same temporary */ 1187e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 1188951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset); 1189951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4); 1190951c6300SRichard Henderson #else 1191951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1192951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4); 1193951c6300SRichard Henderson #endif 1194951c6300SRichard Henderson } 1195951c6300SRichard Henderson 1196d56fea79SRichard Henderson void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1197d56fea79SRichard Henderson { 1198d56fea79SRichard Henderson tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset); 1199d56fea79SRichard Henderson } 1200d56fea79SRichard Henderson 1201d56fea79SRichard Henderson void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1202d56fea79SRichard Henderson { 1203d56fea79SRichard Henderson tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset); 1204d56fea79SRichard Henderson } 1205d56fea79SRichard Henderson 1206d56fea79SRichard Henderson void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1207d56fea79SRichard Henderson { 1208d56fea79SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1209d56fea79SRichard Henderson } 1210d56fea79SRichard Henderson 1211951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1212951c6300SRichard Henderson { 1213e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 1214951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset); 1215951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4); 1216951c6300SRichard Henderson #else 1217951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1218951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4); 1219951c6300SRichard Henderson #endif 1220951c6300SRichard Henderson } 1221951c6300SRichard Henderson 1222d56fea79SRichard Henderson void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1223d56fea79SRichard Henderson { 1224d56fea79SRichard Henderson tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1225d56fea79SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1226d56fea79SRichard Henderson } 1227d56fea79SRichard Henderson 1228d56fea79SRichard Henderson void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1229d56fea79SRichard Henderson { 1230d56fea79SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1231d56fea79SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1232d56fea79SRichard Henderson } 1233d56fea79SRichard Henderson 1234951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1235951c6300SRichard Henderson { 1236951c6300SRichard Henderson tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1237951c6300SRichard Henderson tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1238951c6300SRichard Henderson } 1239951c6300SRichard Henderson 1240951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1241951c6300SRichard Henderson { 1242951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1243951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1244951c6300SRichard Henderson } 1245951c6300SRichard Henderson 1246951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1247951c6300SRichard Henderson { 1248951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1249951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1250951c6300SRichard Henderson } 1251951c6300SRichard Henderson 1252951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1253951c6300SRichard Henderson { 1254951c6300SRichard Henderson gen_helper_shl_i64(ret, arg1, arg2); 1255951c6300SRichard Henderson } 1256951c6300SRichard Henderson 1257951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1258951c6300SRichard Henderson { 1259951c6300SRichard Henderson gen_helper_shr_i64(ret, arg1, arg2); 1260951c6300SRichard Henderson } 1261951c6300SRichard Henderson 1262951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1263951c6300SRichard Henderson { 1264951c6300SRichard Henderson gen_helper_sar_i64(ret, arg1, arg2); 1265951c6300SRichard Henderson } 1266951c6300SRichard Henderson 1267951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1268951c6300SRichard Henderson { 1269951c6300SRichard Henderson TCGv_i64 t0; 1270951c6300SRichard Henderson TCGv_i32 t1; 1271951c6300SRichard Henderson 12725dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 12735dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 1274951c6300SRichard Henderson 1275951c6300SRichard Henderson tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0), 1276951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_LOW(arg2)); 1277951c6300SRichard Henderson 1278951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); 1279951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1280951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2)); 1281951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1282951c6300SRichard Henderson 1283951c6300SRichard Henderson tcg_gen_mov_i64(ret, t0); 1284951c6300SRichard Henderson tcg_temp_free_i64(t0); 1285951c6300SRichard Henderson tcg_temp_free_i32(t1); 1286951c6300SRichard Henderson } 128711d11d61SRichard Henderson 128811d11d61SRichard Henderson #else 128911d11d61SRichard Henderson 129011d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 129111d11d61SRichard Henderson { 129211d11d61SRichard Henderson tcg_gen_mov_i64(ret, tcg_constant_i64(arg)); 129311d11d61SRichard Henderson } 129411d11d61SRichard Henderson 1295951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */ 1296951c6300SRichard Henderson 1297951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1298951c6300SRichard Henderson { 1299951c6300SRichard Henderson /* some cases can be optimized here */ 1300951c6300SRichard Henderson if (arg2 == 0) { 1301951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 130211d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 130311d11d61SRichard Henderson tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2)); 1304951c6300SRichard Henderson } else { 130511d11d61SRichard Henderson tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 130611d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 130711d11d61SRichard Henderson tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1308951c6300SRichard Henderson } 1309951c6300SRichard Henderson } 1310951c6300SRichard Henderson 1311951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2) 1312951c6300SRichard Henderson { 1313951c6300SRichard Henderson if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) { 1314951c6300SRichard Henderson /* Don't recurse with tcg_gen_neg_i64. */ 1315951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2); 131611d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 131711d11d61SRichard Henderson tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2); 1318951c6300SRichard Henderson } else { 131911d11d61SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 132011d11d61SRichard Henderson tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32), 132111d11d61SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1322951c6300SRichard Henderson } 1323951c6300SRichard Henderson } 1324951c6300SRichard Henderson 1325951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1326951c6300SRichard Henderson { 1327951c6300SRichard Henderson /* some cases can be optimized here */ 1328951c6300SRichard Henderson if (arg2 == 0) { 1329951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 133011d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 133111d11d61SRichard Henderson tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2)); 1332951c6300SRichard Henderson } else { 133311d11d61SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 133411d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 133511d11d61SRichard Henderson tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1336951c6300SRichard Henderson } 1337951c6300SRichard Henderson } 1338951c6300SRichard Henderson 1339474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1340951c6300SRichard Henderson { 13413a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1342951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1343951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 13443a13c3f3SRichard Henderson return; 13453a13c3f3SRichard Henderson } 13463a13c3f3SRichard Henderson 1347951c6300SRichard Henderson /* Some cases can be optimized here. */ 1348951c6300SRichard Henderson switch (arg2) { 1349951c6300SRichard Henderson case 0: 1350951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1351951c6300SRichard Henderson return; 1352474b2e8fSRichard Henderson case -1: 1353951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1354951c6300SRichard Henderson return; 1355474b2e8fSRichard Henderson case 0xff: 1356951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i64. */ 1357951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 1358951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1); 1359951c6300SRichard Henderson return; 1360951c6300SRichard Henderson } 1361951c6300SRichard Henderson break; 1362474b2e8fSRichard Henderson case 0xffff: 1363951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 1364951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1); 1365951c6300SRichard Henderson return; 1366951c6300SRichard Henderson } 1367951c6300SRichard Henderson break; 1368474b2e8fSRichard Henderson case 0xffffffffu: 1369951c6300SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 1370951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1); 1371951c6300SRichard Henderson return; 1372951c6300SRichard Henderson } 1373951c6300SRichard Henderson break; 1374951c6300SRichard Henderson } 137511d11d61SRichard Henderson 137611d11d61SRichard Henderson tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2)); 1377951c6300SRichard Henderson } 1378951c6300SRichard Henderson 1379951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1380951c6300SRichard Henderson { 13813a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1382951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1383951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 13843a13c3f3SRichard Henderson return; 13853a13c3f3SRichard Henderson } 1386951c6300SRichard Henderson /* Some cases can be optimized here. */ 1387951c6300SRichard Henderson if (arg2 == -1) { 1388951c6300SRichard Henderson tcg_gen_movi_i64(ret, -1); 1389951c6300SRichard Henderson } else if (arg2 == 0) { 1390951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1391951c6300SRichard Henderson } else { 139211d11d61SRichard Henderson tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2)); 1393951c6300SRichard Henderson } 1394951c6300SRichard Henderson } 1395951c6300SRichard Henderson 1396951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1397951c6300SRichard Henderson { 13983a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1399951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1400951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 14013a13c3f3SRichard Henderson return; 14023a13c3f3SRichard Henderson } 1403951c6300SRichard Henderson /* Some cases can be optimized here. */ 1404951c6300SRichard Henderson if (arg2 == 0) { 1405951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1406951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) { 1407951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i64. */ 1408951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1); 1409951c6300SRichard Henderson } else { 141011d11d61SRichard Henderson tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2)); 1411951c6300SRichard Henderson } 1412951c6300SRichard Henderson } 1413951c6300SRichard Henderson 1414951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, 1415951c6300SRichard Henderson unsigned c, bool right, bool arith) 1416951c6300SRichard Henderson { 1417951c6300SRichard Henderson tcg_debug_assert(c < 64); 1418951c6300SRichard Henderson if (c == 0) { 1419951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1420951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1421951c6300SRichard Henderson } else if (c >= 32) { 1422951c6300SRichard Henderson c -= 32; 1423951c6300SRichard Henderson if (right) { 1424951c6300SRichard Henderson if (arith) { 1425951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1426951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); 1427951c6300SRichard Henderson } else { 1428951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1429951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1430951c6300SRichard Henderson } 1431951c6300SRichard Henderson } else { 1432951c6300SRichard Henderson tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c); 1433951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 1434951c6300SRichard Henderson } 143502616badSRichard Henderson } else if (right) { 143602616badSRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 143702616badSRichard Henderson tcg_gen_extract2_i32(TCGV_LOW(ret), 143802616badSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), c); 1439951c6300SRichard Henderson } else { 1440951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 144102616badSRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret), 144202616badSRichard Henderson TCGV_HIGH(arg1), 32 - c, c); 1443951c6300SRichard Henderson } 144402616badSRichard Henderson if (arith) { 144502616badSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 144602616badSRichard Henderson } else { 144702616badSRichard Henderson tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 144802616badSRichard Henderson } 144902616badSRichard Henderson } else { 145002616badSRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 145102616badSRichard Henderson tcg_gen_extract2_i32(TCGV_HIGH(ret), 145202616badSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c); 145302616badSRichard Henderson } else { 14545dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 145502616badSRichard Henderson tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c); 145602616badSRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), t0, 145702616badSRichard Henderson TCGV_HIGH(arg1), c, 32 - c); 1458951c6300SRichard Henderson tcg_temp_free_i32(t0); 145902616badSRichard Henderson } 146002616badSRichard Henderson tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 1461951c6300SRichard Henderson } 1462951c6300SRichard Henderson } 1463951c6300SRichard Henderson 1464474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1465951c6300SRichard Henderson { 1466474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 14673a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 14683a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0); 14693a13c3f3SRichard Henderson } else if (arg2 == 0) { 1470951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1471951c6300SRichard Henderson } else { 147211d11d61SRichard Henderson tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2)); 1473951c6300SRichard Henderson } 1474951c6300SRichard Henderson } 1475951c6300SRichard Henderson 1476474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1477951c6300SRichard Henderson { 1478474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 14793a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 14803a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0); 14813a13c3f3SRichard Henderson } else if (arg2 == 0) { 1482951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1483951c6300SRichard Henderson } else { 148411d11d61SRichard Henderson tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2)); 1485951c6300SRichard Henderson } 1486951c6300SRichard Henderson } 1487951c6300SRichard Henderson 1488474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1489951c6300SRichard Henderson { 1490474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 14913a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 14923a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1); 14933a13c3f3SRichard Henderson } else if (arg2 == 0) { 1494951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1495951c6300SRichard Henderson } else { 149611d11d61SRichard Henderson tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2)); 1497951c6300SRichard Henderson } 1498951c6300SRichard Henderson } 1499951c6300SRichard Henderson 150042a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l) 1501951c6300SRichard Henderson { 1502951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 150342a268c2SRichard Henderson tcg_gen_br(l); 1504951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 15053a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1506951c6300SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1), 1507951c6300SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), 150842a268c2SRichard Henderson TCGV_HIGH(arg2), cond, label_arg(l)); 15093a13c3f3SRichard Henderson } else { 151042a268c2SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, 151142a268c2SRichard Henderson label_arg(l)); 15123a13c3f3SRichard Henderson } 1513f85b1fc4SRichard Henderson add_last_as_label_use(l); 1514951c6300SRichard Henderson } 1515951c6300SRichard Henderson } 1516951c6300SRichard Henderson 151742a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l) 1518951c6300SRichard Henderson { 151911d11d61SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 152011d11d61SRichard Henderson tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l); 152111d11d61SRichard Henderson } else if (cond == TCG_COND_ALWAYS) { 152242a268c2SRichard Henderson tcg_gen_br(l); 1523951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 152411d11d61SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, 152511d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 152611d11d61SRichard Henderson tcg_constant_i32(arg2), 152711d11d61SRichard Henderson tcg_constant_i32(arg2 >> 32), 152811d11d61SRichard Henderson cond, label_arg(l)); 1529f85b1fc4SRichard Henderson add_last_as_label_use(l); 1530951c6300SRichard Henderson } 1531951c6300SRichard Henderson } 1532951c6300SRichard Henderson 1533951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, 1534951c6300SRichard Henderson TCGv_i64 arg1, TCGv_i64 arg2) 1535951c6300SRichard Henderson { 1536951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 1537951c6300SRichard Henderson tcg_gen_movi_i64(ret, 1); 1538951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 1539951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1540951c6300SRichard Henderson } else { 15413a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1542951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 1543951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 1544951c6300SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 1545951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 15463a13c3f3SRichard Henderson } else { 1547951c6300SRichard Henderson tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); 15483a13c3f3SRichard Henderson } 1549951c6300SRichard Henderson } 1550951c6300SRichard Henderson } 1551951c6300SRichard Henderson 1552951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, 1553951c6300SRichard Henderson TCGv_i64 arg1, int64_t arg2) 1554951c6300SRichard Henderson { 155511d11d61SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 155611d11d61SRichard Henderson tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2)); 155711d11d61SRichard Henderson } else if (cond == TCG_COND_ALWAYS) { 155811d11d61SRichard Henderson tcg_gen_movi_i64(ret, 1); 155911d11d61SRichard Henderson } else if (cond == TCG_COND_NEVER) { 156011d11d61SRichard Henderson tcg_gen_movi_i64(ret, 0); 156111d11d61SRichard Henderson } else { 156211d11d61SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 156311d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 156411d11d61SRichard Henderson tcg_constant_i32(arg2), 156511d11d61SRichard Henderson tcg_constant_i32(arg2 >> 32), cond); 156611d11d61SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 156711d11d61SRichard Henderson } 1568951c6300SRichard Henderson } 1569951c6300SRichard Henderson 1570951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1571951c6300SRichard Henderson { 1572b2e3ae94SRichard Henderson if (arg2 == 0) { 1573b2e3ae94SRichard Henderson tcg_gen_movi_i64(ret, 0); 1574b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 1575b2e3ae94SRichard Henderson tcg_gen_shli_i64(ret, arg1, ctz64(arg2)); 1576b2e3ae94SRichard Henderson } else { 1577f04de891SRichard Henderson tcg_gen_mul_i64(ret, arg1, tcg_constant_i64(arg2)); 1578951c6300SRichard Henderson } 1579b2e3ae94SRichard Henderson } 1580951c6300SRichard Henderson 1581951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1582951c6300SRichard Henderson { 1583951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 1584951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2); 1585951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 15865dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1587951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 1588951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2); 1589951c6300SRichard Henderson tcg_temp_free_i64(t0); 1590951c6300SRichard Henderson } else { 1591951c6300SRichard Henderson gen_helper_div_i64(ret, arg1, arg2); 1592951c6300SRichard Henderson } 1593951c6300SRichard Henderson } 1594951c6300SRichard Henderson 1595951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1596951c6300SRichard Henderson { 1597951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 1598951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2); 1599951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 16005dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1601951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2); 1602951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 1603951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1604951c6300SRichard Henderson tcg_temp_free_i64(t0); 1605951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16065dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1607951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 1608951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2); 1609951c6300SRichard Henderson tcg_temp_free_i64(t0); 1610951c6300SRichard Henderson } else { 1611951c6300SRichard Henderson gen_helper_rem_i64(ret, arg1, arg2); 1612951c6300SRichard Henderson } 1613951c6300SRichard Henderson } 1614951c6300SRichard Henderson 1615951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1616951c6300SRichard Henderson { 1617951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 1618951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2); 1619951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16205dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1621951c6300SRichard Henderson tcg_gen_movi_i64(t0, 0); 1622951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2); 1623951c6300SRichard Henderson tcg_temp_free_i64(t0); 1624951c6300SRichard Henderson } else { 1625951c6300SRichard Henderson gen_helper_divu_i64(ret, arg1, arg2); 1626951c6300SRichard Henderson } 1627951c6300SRichard Henderson } 1628951c6300SRichard Henderson 1629951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1630951c6300SRichard Henderson { 1631951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 1632951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); 1633951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 16345dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1635951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2); 1636951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 1637951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1638951c6300SRichard Henderson tcg_temp_free_i64(t0); 1639951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16405dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1641951c6300SRichard Henderson tcg_gen_movi_i64(t0, 0); 1642951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); 1643951c6300SRichard Henderson tcg_temp_free_i64(t0); 1644951c6300SRichard Henderson } else { 1645951c6300SRichard Henderson gen_helper_remu_i64(ret, arg1, arg2); 1646951c6300SRichard Henderson } 1647951c6300SRichard Henderson } 1648951c6300SRichard Henderson 1649951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg) 1650951c6300SRichard Henderson { 16513a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1652951c6300SRichard Henderson tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1653951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 16543a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8s_i64) { 1655951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg); 1656951c6300SRichard Henderson } else { 1657951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 56); 1658951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 56); 1659951c6300SRichard Henderson } 1660951c6300SRichard Henderson } 1661951c6300SRichard Henderson 1662951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg) 1663951c6300SRichard Henderson { 16643a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1665951c6300SRichard Henderson tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1666951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 16673a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16s_i64) { 1668951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg); 1669951c6300SRichard Henderson } else { 1670951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 48); 1671951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 48); 1672951c6300SRichard Henderson } 1673951c6300SRichard Henderson } 1674951c6300SRichard Henderson 1675951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg) 1676951c6300SRichard Henderson { 16773a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1678951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1679951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 16803a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32s_i64) { 1681951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg); 1682951c6300SRichard Henderson } else { 1683951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 32); 1684951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 32); 1685951c6300SRichard Henderson } 1686951c6300SRichard Henderson } 1687951c6300SRichard Henderson 1688951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg) 1689951c6300SRichard Henderson { 16903a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1691951c6300SRichard Henderson tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1692951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 16933a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8u_i64) { 1694951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg); 1695951c6300SRichard Henderson } else { 1696951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffu); 1697951c6300SRichard Henderson } 1698951c6300SRichard Henderson } 1699951c6300SRichard Henderson 1700951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg) 1701951c6300SRichard Henderson { 17023a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1703951c6300SRichard Henderson tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1704951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17053a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16u_i64) { 1706951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg); 1707951c6300SRichard Henderson } else { 1708951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffu); 1709951c6300SRichard Henderson } 1710951c6300SRichard Henderson } 1711951c6300SRichard Henderson 1712951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg) 1713951c6300SRichard Henderson { 17143a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1715951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1716951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17173a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32u_i64) { 1718951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg); 1719951c6300SRichard Henderson } else { 1720951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffffffu); 1721951c6300SRichard Henderson } 1722951c6300SRichard Henderson } 1723951c6300SRichard Henderson 17242b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 1725951c6300SRichard Henderson { 17262b836c2aSRichard Henderson /* Only one extension flag may be present. */ 17272b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 17282b836c2aSRichard Henderson 17293a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17302b836c2aSRichard Henderson tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags); 17312b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 17322b836c2aSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 17332b836c2aSRichard Henderson } else { 1734951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17352b836c2aSRichard Henderson } 17363a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap16_i64) { 17372b836c2aSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags); 1738951c6300SRichard Henderson } else { 17395dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 17405dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 1741951c6300SRichard Henderson 17422b836c2aSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); 17432b836c2aSRichard Henderson if (!(flags & TCG_BSWAP_IZ)) { 17442b836c2aSRichard Henderson tcg_gen_ext8u_i64(t0, t0); 17452b836c2aSRichard Henderson } 17462b836c2aSRichard Henderson 17472b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 17482b836c2aSRichard Henderson tcg_gen_shli_i64(t1, arg, 56); 17492b836c2aSRichard Henderson tcg_gen_sari_i64(t1, t1, 48); 17502b836c2aSRichard Henderson } else if (flags & TCG_BSWAP_OZ) { 17512b836c2aSRichard Henderson tcg_gen_ext8u_i64(t1, arg); 17522b836c2aSRichard Henderson tcg_gen_shli_i64(t1, t1, 8); 17532b836c2aSRichard Henderson } else { 17542b836c2aSRichard Henderson tcg_gen_shli_i64(t1, arg, 8); 17552b836c2aSRichard Henderson } 17562b836c2aSRichard Henderson 17572b836c2aSRichard Henderson tcg_gen_or_i64(ret, t0, t1); 1758951c6300SRichard Henderson tcg_temp_free_i64(t0); 17592b836c2aSRichard Henderson tcg_temp_free_i64(t1); 1760951c6300SRichard Henderson } 1761951c6300SRichard Henderson } 1762951c6300SRichard Henderson 17632b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 1764951c6300SRichard Henderson { 17652b836c2aSRichard Henderson /* Only one extension flag may be present. */ 17662b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 17672b836c2aSRichard Henderson 17683a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1769951c6300SRichard Henderson tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 17702b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 17712b836c2aSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 17722b836c2aSRichard Henderson } else { 1773951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17742b836c2aSRichard Henderson } 17753a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap32_i64) { 17762b836c2aSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags); 1777951c6300SRichard Henderson } else { 17785dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 17795dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 178011d11d61SRichard Henderson TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff); 1781951c6300SRichard Henderson 17822b836c2aSRichard Henderson /* arg = xxxxabcd */ 17832b836c2aSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .xxxxabc */ 1784a686dc71SRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */ 1785a686dc71SRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */ 1786a686dc71SRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */ 1787a686dc71SRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */ 1788951c6300SRichard Henderson 1789a686dc71SRichard Henderson tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */ 1790a686dc71SRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */ 17912b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 17922b836c2aSRichard Henderson tcg_gen_sari_i64(t1, t1, 32); /* t1 = ssssdc.. */ 17932b836c2aSRichard Henderson } else { 1794a686dc71SRichard Henderson tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */ 17952b836c2aSRichard Henderson } 17962b836c2aSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba */ 1797951c6300SRichard Henderson 1798951c6300SRichard Henderson tcg_temp_free_i64(t0); 1799951c6300SRichard Henderson tcg_temp_free_i64(t1); 1800951c6300SRichard Henderson } 1801951c6300SRichard Henderson } 1802951c6300SRichard Henderson 1803951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg) 1804951c6300SRichard Henderson { 18053a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1806951c6300SRichard Henderson TCGv_i32 t0, t1; 18075dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 18085dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 1809951c6300SRichard Henderson 1810951c6300SRichard Henderson tcg_gen_bswap32_i32(t0, TCGV_LOW(arg)); 1811951c6300SRichard Henderson tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg)); 1812951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), t1); 1813951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t0); 1814951c6300SRichard Henderson tcg_temp_free_i32(t0); 1815951c6300SRichard Henderson tcg_temp_free_i32(t1); 18163a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap64_i64) { 1817587195bdSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0); 1818951c6300SRichard Henderson } else { 18195dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 18205dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 18215dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 1822951c6300SRichard Henderson 18239e821eabSRichard Henderson /* arg = abcdefgh */ 18249e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull); 18259e821eabSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .abcdefg */ 18269e821eabSRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .b.d.f.h */ 18279e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .a.c.e.g */ 18289e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = b.d.f.h. */ 18299e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = badcfehg */ 1830951c6300SRichard Henderson 18319e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull); 18329e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ..badcfe */ 18339e821eabSRichard Henderson tcg_gen_and_i64(t1, ret, t2); /* t1 = ..dc..hg */ 18349e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = ..ba..fe */ 18359e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 16); /* t1 = dc..hg.. */ 18369e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = dcbahgfe */ 1837951c6300SRichard Henderson 18389e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 32); /* t0 = ....dcba */ 18399e821eabSRichard Henderson tcg_gen_shli_i64(t1, ret, 32); /* t1 = hgfe.... */ 18409e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = hgfedcba */ 1841951c6300SRichard Henderson 1842951c6300SRichard Henderson tcg_temp_free_i64(t0); 1843951c6300SRichard Henderson tcg_temp_free_i64(t1); 18449e821eabSRichard Henderson tcg_temp_free_i64(t2); 1845951c6300SRichard Henderson } 1846951c6300SRichard Henderson } 1847951c6300SRichard Henderson 184846be8425SRichard Henderson void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg) 184946be8425SRichard Henderson { 185046be8425SRichard Henderson uint64_t m = 0x0000ffff0000ffffull; 18515dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 18525dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 185346be8425SRichard Henderson 185446be8425SRichard Henderson /* See include/qemu/bitops.h, hswap64. */ 185546be8425SRichard Henderson tcg_gen_rotli_i64(t1, arg, 32); 185646be8425SRichard Henderson tcg_gen_andi_i64(t0, t1, m); 185746be8425SRichard Henderson tcg_gen_shli_i64(t0, t0, 16); 185846be8425SRichard Henderson tcg_gen_shri_i64(t1, t1, 16); 185946be8425SRichard Henderson tcg_gen_andi_i64(t1, t1, m); 186046be8425SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 186146be8425SRichard Henderson 186246be8425SRichard Henderson tcg_temp_free_i64(t0); 186346be8425SRichard Henderson tcg_temp_free_i64(t1); 186446be8425SRichard Henderson } 186546be8425SRichard Henderson 186646be8425SRichard Henderson void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg) 186746be8425SRichard Henderson { 186846be8425SRichard Henderson /* Swapping 2 32-bit elements is a rotate. */ 186946be8425SRichard Henderson tcg_gen_rotli_i64(ret, arg, 32); 187046be8425SRichard Henderson } 187146be8425SRichard Henderson 1872951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg) 1873951c6300SRichard Henderson { 18743a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 18753a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 18763a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 18773a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_not_i64) { 1878951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg); 1879951c6300SRichard Henderson } else { 1880951c6300SRichard Henderson tcg_gen_xori_i64(ret, arg, -1); 1881951c6300SRichard Henderson } 1882951c6300SRichard Henderson } 1883951c6300SRichard Henderson 1884951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1885951c6300SRichard Henderson { 18863a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 18873a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 18883a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 18893a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_andc_i64) { 1890951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2); 1891951c6300SRichard Henderson } else { 18925dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1893951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 1894951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, t0); 1895951c6300SRichard Henderson tcg_temp_free_i64(t0); 1896951c6300SRichard Henderson } 1897951c6300SRichard Henderson } 1898951c6300SRichard Henderson 1899951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1900951c6300SRichard Henderson { 19013a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19023a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 19033a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 19043a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_eqv_i64) { 1905951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2); 1906951c6300SRichard Henderson } else { 1907951c6300SRichard Henderson tcg_gen_xor_i64(ret, arg1, arg2); 1908951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 1909951c6300SRichard Henderson } 1910951c6300SRichard Henderson } 1911951c6300SRichard Henderson 1912951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1913951c6300SRichard Henderson { 19143a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19153a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 19163a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 19173a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nand_i64) { 1918951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2); 1919951c6300SRichard Henderson } else { 1920951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, arg2); 1921951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 1922951c6300SRichard Henderson } 1923951c6300SRichard Henderson } 1924951c6300SRichard Henderson 1925951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1926951c6300SRichard Henderson { 19273a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19283a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 19293a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 19303a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nor_i64) { 1931951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2); 1932951c6300SRichard Henderson } else { 1933951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, arg2); 1934951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 1935951c6300SRichard Henderson } 1936951c6300SRichard Henderson } 1937951c6300SRichard Henderson 1938951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1939951c6300SRichard Henderson { 19403a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19413a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 19423a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 19433a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_orc_i64) { 1944951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2); 1945951c6300SRichard Henderson } else { 19465dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1947951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 1948951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, t0); 1949951c6300SRichard Henderson tcg_temp_free_i64(t0); 1950951c6300SRichard Henderson } 1951951c6300SRichard Henderson } 1952951c6300SRichard Henderson 19530e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 19540e28d006SRichard Henderson { 19550e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i64) { 19560e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2); 19570e28d006SRichard Henderson } else { 19580e28d006SRichard Henderson gen_helper_clz_i64(ret, arg1, arg2); 19590e28d006SRichard Henderson } 19600e28d006SRichard Henderson } 19610e28d006SRichard Henderson 19620e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 19630e28d006SRichard Henderson { 19640e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 19650e28d006SRichard Henderson && TCG_TARGET_HAS_clz_i32 19660e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 19675dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 196811d11d61SRichard Henderson tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32); 19690e28d006SRichard Henderson tcg_gen_addi_i32(t, t, 32); 19700e28d006SRichard Henderson tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t); 19710e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 19720e28d006SRichard Henderson tcg_temp_free_i32(t); 19730e28d006SRichard Henderson } else { 1974f04de891SRichard Henderson tcg_gen_clz_i64(ret, arg1, tcg_constant_i64(arg2)); 19750e28d006SRichard Henderson } 19760e28d006SRichard Henderson } 19770e28d006SRichard Henderson 19780e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 19790e28d006SRichard Henderson { 19800e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i64) { 19810e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2); 198214e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) { 19835dd48602SRichard Henderson TCGv_i64 z, t = tcg_temp_ebb_new_i64(); 198414e99210SRichard Henderson 198514e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 198614e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 198714e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 198814e99210SRichard Henderson tcg_gen_ctpop_i64(t, t); 198914e99210SRichard Henderson } else { 199014e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 64, don't fight it. */ 199114e99210SRichard Henderson tcg_gen_neg_i64(t, arg1); 199214e99210SRichard Henderson tcg_gen_and_i64(t, t, arg1); 199314e99210SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 199414e99210SRichard Henderson tcg_gen_xori_i64(t, t, 63); 199514e99210SRichard Henderson } 199611d11d61SRichard Henderson z = tcg_constant_i64(0); 199714e99210SRichard Henderson tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t); 199814e99210SRichard Henderson tcg_temp_free_i64(t); 199914e99210SRichard Henderson tcg_temp_free_i64(z); 20000e28d006SRichard Henderson } else { 20010e28d006SRichard Henderson gen_helper_ctz_i64(ret, arg1, arg2); 20020e28d006SRichard Henderson } 20030e28d006SRichard Henderson } 20040e28d006SRichard Henderson 20050e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 20060e28d006SRichard Henderson { 20070e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 20080e28d006SRichard Henderson && TCG_TARGET_HAS_ctz_i32 20090e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 20105dd48602SRichard Henderson TCGv_i32 t32 = tcg_temp_ebb_new_i32(); 201111d11d61SRichard Henderson tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32); 20120e28d006SRichard Henderson tcg_gen_addi_i32(t32, t32, 32); 20130e28d006SRichard Henderson tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32); 20140e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 20150e28d006SRichard Henderson tcg_temp_free_i32(t32); 201614e99210SRichard Henderson } else if (!TCG_TARGET_HAS_ctz_i64 201714e99210SRichard Henderson && TCG_TARGET_HAS_ctpop_i64 201814e99210SRichard Henderson && arg2 == 64) { 201914e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 20205dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 202114e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 202214e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 202314e99210SRichard Henderson tcg_gen_ctpop_i64(ret, t); 202414e99210SRichard Henderson tcg_temp_free_i64(t); 20250e28d006SRichard Henderson } else { 2026f04de891SRichard Henderson tcg_gen_ctz_i64(ret, arg1, tcg_constant_i64(arg2)); 20270e28d006SRichard Henderson } 20280e28d006SRichard Henderson } 20290e28d006SRichard Henderson 2030086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg) 2031086920c2SRichard Henderson { 2032086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) { 20335dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2034086920c2SRichard Henderson tcg_gen_sari_i64(t, arg, 63); 2035086920c2SRichard Henderson tcg_gen_xor_i64(t, t, arg); 2036086920c2SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 2037086920c2SRichard Henderson tcg_gen_subi_i64(ret, t, 1); 2038086920c2SRichard Henderson tcg_temp_free_i64(t); 2039086920c2SRichard Henderson } else { 2040086920c2SRichard Henderson gen_helper_clrsb_i64(ret, arg); 2041086920c2SRichard Henderson } 2042086920c2SRichard Henderson } 2043086920c2SRichard Henderson 2044a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1) 2045a768e4e9SRichard Henderson { 2046a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 2047a768e4e9SRichard Henderson tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1); 2048a768e4e9SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) { 2049a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2050a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2051a768e4e9SRichard Henderson tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret)); 2052a768e4e9SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2053a768e4e9SRichard Henderson } else { 2054a768e4e9SRichard Henderson gen_helper_ctpop_i64(ret, arg1); 2055a768e4e9SRichard Henderson } 2056a768e4e9SRichard Henderson } 2057a768e4e9SRichard Henderson 2058951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2059951c6300SRichard Henderson { 2060951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 2061951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2); 2062951c6300SRichard Henderson } else { 2063951c6300SRichard Henderson TCGv_i64 t0, t1; 20645dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 20655dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2066951c6300SRichard Henderson tcg_gen_shl_i64(t0, arg1, arg2); 2067951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 2068951c6300SRichard Henderson tcg_gen_shr_i64(t1, arg1, t1); 2069951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2070951c6300SRichard Henderson tcg_temp_free_i64(t0); 2071951c6300SRichard Henderson tcg_temp_free_i64(t1); 2072951c6300SRichard Henderson } 2073951c6300SRichard Henderson } 2074951c6300SRichard Henderson 207507dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2076951c6300SRichard Henderson { 207707dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2078951c6300SRichard Henderson /* some cases can be optimized here */ 2079951c6300SRichard Henderson if (arg2 == 0) { 2080951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 2081951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i64) { 208211d11d61SRichard Henderson tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2)); 2083951c6300SRichard Henderson } else { 2084951c6300SRichard Henderson TCGv_i64 t0, t1; 20855dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 20865dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2087951c6300SRichard Henderson tcg_gen_shli_i64(t0, arg1, arg2); 2088951c6300SRichard Henderson tcg_gen_shri_i64(t1, arg1, 64 - arg2); 2089951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2090951c6300SRichard Henderson tcg_temp_free_i64(t0); 2091951c6300SRichard Henderson tcg_temp_free_i64(t1); 2092951c6300SRichard Henderson } 2093951c6300SRichard Henderson } 2094951c6300SRichard Henderson 2095951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2096951c6300SRichard Henderson { 2097951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 2098951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2); 2099951c6300SRichard Henderson } else { 2100951c6300SRichard Henderson TCGv_i64 t0, t1; 21015dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 21025dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2103951c6300SRichard Henderson tcg_gen_shr_i64(t0, arg1, arg2); 2104951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 2105951c6300SRichard Henderson tcg_gen_shl_i64(t1, arg1, t1); 2106951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2107951c6300SRichard Henderson tcg_temp_free_i64(t0); 2108951c6300SRichard Henderson tcg_temp_free_i64(t1); 2109951c6300SRichard Henderson } 2110951c6300SRichard Henderson } 2111951c6300SRichard Henderson 211207dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2113951c6300SRichard Henderson { 211407dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2115951c6300SRichard Henderson /* some cases can be optimized here */ 2116951c6300SRichard Henderson if (arg2 == 0) { 2117951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 2118951c6300SRichard Henderson } else { 2119951c6300SRichard Henderson tcg_gen_rotli_i64(ret, arg1, 64 - arg2); 2120951c6300SRichard Henderson } 2121951c6300SRichard Henderson } 2122951c6300SRichard Henderson 2123951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, 2124951c6300SRichard Henderson unsigned int ofs, unsigned int len) 2125951c6300SRichard Henderson { 2126951c6300SRichard Henderson uint64_t mask; 2127951c6300SRichard Henderson TCGv_i64 t1; 2128951c6300SRichard Henderson 2129951c6300SRichard Henderson tcg_debug_assert(ofs < 64); 21300d0d309dSRichard Henderson tcg_debug_assert(len > 0); 2131951c6300SRichard Henderson tcg_debug_assert(len <= 64); 2132951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 64); 2133951c6300SRichard Henderson 21340d0d309dSRichard Henderson if (len == 64) { 2135951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg2); 2136951c6300SRichard Henderson return; 2137951c6300SRichard Henderson } 2138951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) { 2139951c6300SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); 2140951c6300SRichard Henderson return; 2141951c6300SRichard Henderson } 2142951c6300SRichard Henderson 21433a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2144951c6300SRichard Henderson if (ofs >= 32) { 2145951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 2146951c6300SRichard Henderson TCGV_LOW(arg2), ofs - 32, len); 2147951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2148951c6300SRichard Henderson return; 2149951c6300SRichard Henderson } 2150951c6300SRichard Henderson if (ofs + len <= 32) { 2151951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1), 2152951c6300SRichard Henderson TCGV_LOW(arg2), ofs, len); 2153951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2154951c6300SRichard Henderson return; 2155951c6300SRichard Henderson } 21563a13c3f3SRichard Henderson } 2157951c6300SRichard Henderson 21585dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2159951c6300SRichard Henderson 2160b0a60567SRichard Henderson if (TCG_TARGET_HAS_extract2_i64) { 2161b0a60567SRichard Henderson if (ofs + len == 64) { 2162b0a60567SRichard Henderson tcg_gen_shli_i64(t1, arg1, len); 2163b0a60567SRichard Henderson tcg_gen_extract2_i64(ret, t1, arg2, len); 2164b0a60567SRichard Henderson goto done; 2165b0a60567SRichard Henderson } 2166b0a60567SRichard Henderson if (ofs == 0) { 2167b0a60567SRichard Henderson tcg_gen_extract2_i64(ret, arg1, arg2, len); 2168b0a60567SRichard Henderson tcg_gen_rotli_i64(ret, ret, len); 2169b0a60567SRichard Henderson goto done; 2170b0a60567SRichard Henderson } 2171b0a60567SRichard Henderson } 2172b0a60567SRichard Henderson 2173b0a60567SRichard Henderson mask = (1ull << len) - 1; 2174951c6300SRichard Henderson if (ofs + len < 64) { 2175951c6300SRichard Henderson tcg_gen_andi_i64(t1, arg2, mask); 2176951c6300SRichard Henderson tcg_gen_shli_i64(t1, t1, ofs); 2177951c6300SRichard Henderson } else { 2178951c6300SRichard Henderson tcg_gen_shli_i64(t1, arg2, ofs); 2179951c6300SRichard Henderson } 2180951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg1, ~(mask << ofs)); 2181951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2182b0a60567SRichard Henderson done: 2183951c6300SRichard Henderson tcg_temp_free_i64(t1); 2184951c6300SRichard Henderson } 2185951c6300SRichard Henderson 218607cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, 218707cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 218807cc68d5SRichard Henderson { 218907cc68d5SRichard Henderson tcg_debug_assert(ofs < 64); 219007cc68d5SRichard Henderson tcg_debug_assert(len > 0); 219107cc68d5SRichard Henderson tcg_debug_assert(len <= 64); 219207cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 64); 219307cc68d5SRichard Henderson 219407cc68d5SRichard Henderson if (ofs + len == 64) { 219507cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 219607cc68d5SRichard Henderson } else if (ofs == 0) { 219707cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 219807cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i64 219907cc68d5SRichard Henderson && TCG_TARGET_deposit_i64_valid(ofs, len)) { 220011d11d61SRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 220107cc68d5SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); 220207cc68d5SRichard Henderson } else { 220307cc68d5SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 220407cc68d5SRichard Henderson if (ofs >= 32) { 220507cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg), 220607cc68d5SRichard Henderson ofs - 32, len); 220707cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 220807cc68d5SRichard Henderson return; 220907cc68d5SRichard Henderson } 221007cc68d5SRichard Henderson if (ofs + len <= 32) { 221107cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 221207cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 221307cc68d5SRichard Henderson return; 221407cc68d5SRichard Henderson } 221507cc68d5SRichard Henderson } 221607cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 221707cc68d5SRichard Henderson which allows ARG to stay live. */ 221807cc68d5SRichard Henderson switch (len) { 221907cc68d5SRichard Henderson case 32: 222007cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 222107cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 222207cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 222307cc68d5SRichard Henderson return; 222407cc68d5SRichard Henderson } 222507cc68d5SRichard Henderson break; 222607cc68d5SRichard Henderson case 16: 222707cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 222807cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 222907cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 223007cc68d5SRichard Henderson return; 223107cc68d5SRichard Henderson } 223207cc68d5SRichard Henderson break; 223307cc68d5SRichard Henderson case 8: 223407cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 223507cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 223607cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 223707cc68d5SRichard Henderson return; 223807cc68d5SRichard Henderson } 223907cc68d5SRichard Henderson break; 224007cc68d5SRichard Henderson } 224107cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 224207cc68d5SRichard Henderson switch (ofs + len) { 224307cc68d5SRichard Henderson case 32: 224407cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 224507cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 224607cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, ret); 224707cc68d5SRichard Henderson return; 224807cc68d5SRichard Henderson } 224907cc68d5SRichard Henderson break; 225007cc68d5SRichard Henderson case 16: 225107cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 225207cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 225307cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, ret); 225407cc68d5SRichard Henderson return; 225507cc68d5SRichard Henderson } 225607cc68d5SRichard Henderson break; 225707cc68d5SRichard Henderson case 8: 225807cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 225907cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 226007cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, ret); 226107cc68d5SRichard Henderson return; 226207cc68d5SRichard Henderson } 226307cc68d5SRichard Henderson break; 226407cc68d5SRichard Henderson } 226507cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 226607cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 226707cc68d5SRichard Henderson } 226807cc68d5SRichard Henderson } 226907cc68d5SRichard Henderson 22707ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, 22717ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 22727ec8bab3SRichard Henderson { 22737ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 22747ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 22757ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 22767ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 22777ec8bab3SRichard Henderson 22787ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 22797ec8bab3SRichard Henderson if (ofs + len == 64) { 22807ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, 64 - len); 22817ec8bab3SRichard Henderson return; 22827ec8bab3SRichard Henderson } 22837ec8bab3SRichard Henderson if (ofs == 0) { 22847ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 22857ec8bab3SRichard Henderson return; 22867ec8bab3SRichard Henderson } 22877ec8bab3SRichard Henderson 22887ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 22897ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 22907ec8bab3SRichard Henderson if (ofs >= 32) { 22917ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 22927ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 22937ec8bab3SRichard Henderson return; 22947ec8bab3SRichard Henderson } 22957ec8bab3SRichard Henderson if (ofs + len <= 32) { 22967ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 22977ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 22987ec8bab3SRichard Henderson return; 22997ec8bab3SRichard Henderson } 23007ec8bab3SRichard Henderson /* The field is split across two words. One double-word 23017ec8bab3SRichard Henderson shift is better than two double-word shifts. */ 23027ec8bab3SRichard Henderson goto do_shift_and; 23037ec8bab3SRichard Henderson } 23047ec8bab3SRichard Henderson 23057ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i64 23067ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 23077ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len); 23087ec8bab3SRichard Henderson return; 23097ec8bab3SRichard Henderson } 23107ec8bab3SRichard Henderson 23117ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 23127ec8bab3SRichard Henderson switch (ofs + len) { 23137ec8bab3SRichard Henderson case 32: 23147ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 23157ec8bab3SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 23167ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 23177ec8bab3SRichard Henderson return; 23187ec8bab3SRichard Henderson } 23197ec8bab3SRichard Henderson break; 23207ec8bab3SRichard Henderson case 16: 23217ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 23227ec8bab3SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 23237ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 23247ec8bab3SRichard Henderson return; 23257ec8bab3SRichard Henderson } 23267ec8bab3SRichard Henderson break; 23277ec8bab3SRichard Henderson case 8: 23287ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 23297ec8bab3SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 23307ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 23317ec8bab3SRichard Henderson return; 23327ec8bab3SRichard Henderson } 23337ec8bab3SRichard Henderson break; 23347ec8bab3SRichard Henderson } 23357ec8bab3SRichard Henderson 23367ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 23377ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special cases of 16 and 32, 23387ec8bab3SRichard Henderson so that we get ext8u, ext16u, and ext32u. */ 23397ec8bab3SRichard Henderson switch (len) { 23407ec8bab3SRichard Henderson case 1 ... 8: case 16: case 32: 23417ec8bab3SRichard Henderson do_shift_and: 23427ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 23437ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, ret, (1ull << len) - 1); 23447ec8bab3SRichard Henderson break; 23457ec8bab3SRichard Henderson default: 23467ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 23477ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, 64 - len); 23487ec8bab3SRichard Henderson break; 23497ec8bab3SRichard Henderson } 23507ec8bab3SRichard Henderson } 23517ec8bab3SRichard Henderson 23527ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg, 23537ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 23547ec8bab3SRichard Henderson { 23557ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 23567ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 23577ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 23587ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 23597ec8bab3SRichard Henderson 23607ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if sextract is supported. */ 23617ec8bab3SRichard Henderson if (ofs + len == 64) { 23627ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, arg, 64 - len); 23637ec8bab3SRichard Henderson return; 23647ec8bab3SRichard Henderson } 23657ec8bab3SRichard Henderson if (ofs == 0) { 23667ec8bab3SRichard Henderson switch (len) { 23677ec8bab3SRichard Henderson case 32: 23687ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 23697ec8bab3SRichard Henderson return; 23707ec8bab3SRichard Henderson case 16: 23717ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 23727ec8bab3SRichard Henderson return; 23737ec8bab3SRichard Henderson case 8: 23747ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 23757ec8bab3SRichard Henderson return; 23767ec8bab3SRichard Henderson } 23777ec8bab3SRichard Henderson } 23787ec8bab3SRichard Henderson 23797ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 23807ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 23817ec8bab3SRichard Henderson if (ofs >= 32) { 23827ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 23837ec8bab3SRichard Henderson } else if (ofs + len <= 32) { 23847ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 23857ec8bab3SRichard Henderson } else if (ofs == 0) { 23867ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 23877ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32); 23887ec8bab3SRichard Henderson return; 23897ec8bab3SRichard Henderson } else if (len > 32) { 23905dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 23917ec8bab3SRichard Henderson /* Extract the bits for the high word normally. */ 23927ec8bab3SRichard Henderson tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32); 23937ec8bab3SRichard Henderson /* Shift the field down for the low part. */ 23947ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 23957ec8bab3SRichard Henderson /* Overwrite the shift into the high part. */ 23967ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t); 23977ec8bab3SRichard Henderson tcg_temp_free_i32(t); 23987ec8bab3SRichard Henderson return; 23997ec8bab3SRichard Henderson } else { 24007ec8bab3SRichard Henderson /* Shift the field down for the low part, such that the 24017ec8bab3SRichard Henderson field sits at the MSB. */ 24027ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs + len - 32); 24037ec8bab3SRichard Henderson /* Shift the field down from the MSB, sign extending. */ 24047ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len); 24057ec8bab3SRichard Henderson } 24067ec8bab3SRichard Henderson /* Sign-extend the field from 32 bits. */ 24077ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 24087ec8bab3SRichard Henderson return; 24097ec8bab3SRichard Henderson } 24107ec8bab3SRichard Henderson 24117ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i64 24127ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 24137ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); 24147ec8bab3SRichard Henderson return; 24157ec8bab3SRichard Henderson } 24167ec8bab3SRichard Henderson 24177ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 24187ec8bab3SRichard Henderson switch (ofs + len) { 24197ec8bab3SRichard Henderson case 32: 24207ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 24217ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 24227ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 24237ec8bab3SRichard Henderson return; 24247ec8bab3SRichard Henderson } 24257ec8bab3SRichard Henderson break; 24267ec8bab3SRichard Henderson case 16: 24277ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 24287ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 24297ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 24307ec8bab3SRichard Henderson return; 24317ec8bab3SRichard Henderson } 24327ec8bab3SRichard Henderson break; 24337ec8bab3SRichard Henderson case 8: 24347ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 24357ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 24367ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 24377ec8bab3SRichard Henderson return; 24387ec8bab3SRichard Henderson } 24397ec8bab3SRichard Henderson break; 24407ec8bab3SRichard Henderson } 24417ec8bab3SRichard Henderson switch (len) { 24427ec8bab3SRichard Henderson case 32: 24437ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 24447ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 24457ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, ret); 24467ec8bab3SRichard Henderson return; 24477ec8bab3SRichard Henderson } 24487ec8bab3SRichard Henderson break; 24497ec8bab3SRichard Henderson case 16: 24507ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 24517ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 24527ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, ret); 24537ec8bab3SRichard Henderson return; 24547ec8bab3SRichard Henderson } 24557ec8bab3SRichard Henderson break; 24567ec8bab3SRichard Henderson case 8: 24577ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 24587ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 24597ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, ret); 24607ec8bab3SRichard Henderson return; 24617ec8bab3SRichard Henderson } 24627ec8bab3SRichard Henderson break; 24637ec8bab3SRichard Henderson } 24647ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 24657ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, 64 - len); 24667ec8bab3SRichard Henderson } 24677ec8bab3SRichard Henderson 24682089fcc9SDavid Hildenbrand /* 24692089fcc9SDavid Hildenbrand * Extract 64 bits from a 128-bit input, ah:al, starting from ofs. 24702089fcc9SDavid Hildenbrand * Unlike tcg_gen_extract_i64 above, len is fixed at 64. 24712089fcc9SDavid Hildenbrand */ 24722089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah, 24732089fcc9SDavid Hildenbrand unsigned int ofs) 24742089fcc9SDavid Hildenbrand { 24752089fcc9SDavid Hildenbrand tcg_debug_assert(ofs <= 64); 24762089fcc9SDavid Hildenbrand if (ofs == 0) { 24772089fcc9SDavid Hildenbrand tcg_gen_mov_i64(ret, al); 24782089fcc9SDavid Hildenbrand } else if (ofs == 64) { 24792089fcc9SDavid Hildenbrand tcg_gen_mov_i64(ret, ah); 24802089fcc9SDavid Hildenbrand } else if (al == ah) { 24812089fcc9SDavid Hildenbrand tcg_gen_rotri_i64(ret, al, ofs); 2482fce1296fSRichard Henderson } else if (TCG_TARGET_HAS_extract2_i64) { 2483fce1296fSRichard Henderson tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs); 24842089fcc9SDavid Hildenbrand } else { 24855dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 24862089fcc9SDavid Hildenbrand tcg_gen_shri_i64(t0, al, ofs); 24872089fcc9SDavid Hildenbrand tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs); 24882089fcc9SDavid Hildenbrand tcg_temp_free_i64(t0); 24892089fcc9SDavid Hildenbrand } 24902089fcc9SDavid Hildenbrand } 24912089fcc9SDavid Hildenbrand 2492951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, 2493951c6300SRichard Henderson TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2) 2494951c6300SRichard Henderson { 249537ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 249637ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v1); 249737ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 249837ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v2); 249937ed3bf1SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 25005dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 25015dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 2502951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, 2503951c6300SRichard Henderson TCGV_LOW(c1), TCGV_HIGH(c1), 2504951c6300SRichard Henderson TCGV_LOW(c2), TCGV_HIGH(c2), cond); 2505951c6300SRichard Henderson 2506951c6300SRichard Henderson if (TCG_TARGET_HAS_movcond_i32) { 2507951c6300SRichard Henderson tcg_gen_movi_i32(t1, 0); 2508951c6300SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1, 2509951c6300SRichard Henderson TCGV_LOW(v1), TCGV_LOW(v2)); 2510951c6300SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1, 2511951c6300SRichard Henderson TCGV_HIGH(v1), TCGV_HIGH(v2)); 2512951c6300SRichard Henderson } else { 2513951c6300SRichard Henderson tcg_gen_neg_i32(t0, t0); 2514951c6300SRichard Henderson 2515951c6300SRichard Henderson tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); 2516951c6300SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); 2517951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); 2518951c6300SRichard Henderson 2519951c6300SRichard Henderson tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); 2520951c6300SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); 2521951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); 2522951c6300SRichard Henderson } 2523951c6300SRichard Henderson tcg_temp_free_i32(t0); 2524951c6300SRichard Henderson tcg_temp_free_i32(t1); 25253a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_movcond_i64) { 2526951c6300SRichard Henderson tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); 2527951c6300SRichard Henderson } else { 25285dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 25295dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 2530951c6300SRichard Henderson tcg_gen_setcond_i64(cond, t0, c1, c2); 2531951c6300SRichard Henderson tcg_gen_neg_i64(t0, t0); 2532951c6300SRichard Henderson tcg_gen_and_i64(t1, v1, t0); 2533951c6300SRichard Henderson tcg_gen_andc_i64(ret, v2, t0); 2534951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2535951c6300SRichard Henderson tcg_temp_free_i64(t0); 2536951c6300SRichard Henderson tcg_temp_free_i64(t1); 2537951c6300SRichard Henderson } 2538951c6300SRichard Henderson } 2539951c6300SRichard Henderson 2540951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2541951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2542951c6300SRichard Henderson { 2543951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i64) { 2544951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh); 2545951c6300SRichard Henderson } else { 25465dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 25475dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 2548951c6300SRichard Henderson tcg_gen_add_i64(t0, al, bl); 2549951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al); 2550951c6300SRichard Henderson tcg_gen_add_i64(rh, ah, bh); 2551951c6300SRichard Henderson tcg_gen_add_i64(rh, rh, t1); 2552951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2553951c6300SRichard Henderson tcg_temp_free_i64(t0); 2554951c6300SRichard Henderson tcg_temp_free_i64(t1); 2555951c6300SRichard Henderson } 2556951c6300SRichard Henderson } 2557951c6300SRichard Henderson 2558951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2559951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2560951c6300SRichard Henderson { 2561951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i64) { 2562951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh); 2563951c6300SRichard Henderson } else { 25645dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 25655dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 2566951c6300SRichard Henderson tcg_gen_sub_i64(t0, al, bl); 2567951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl); 2568951c6300SRichard Henderson tcg_gen_sub_i64(rh, ah, bh); 2569951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t1); 2570951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2571951c6300SRichard Henderson tcg_temp_free_i64(t0); 2572951c6300SRichard Henderson tcg_temp_free_i64(t1); 2573951c6300SRichard Henderson } 2574951c6300SRichard Henderson } 2575951c6300SRichard Henderson 2576951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2577951c6300SRichard Henderson { 2578951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i64) { 2579951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); 2580951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i64) { 25815dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2582951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2583951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2); 2584951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 2585951c6300SRichard Henderson tcg_temp_free_i64(t); 2586951c6300SRichard Henderson } else { 25875dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2588951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 2589951c6300SRichard Henderson gen_helper_muluh_i64(rh, arg1, arg2); 2590951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2591951c6300SRichard Henderson tcg_temp_free_i64(t0); 2592951c6300SRichard Henderson } 2593951c6300SRichard Henderson } 2594951c6300SRichard Henderson 2595951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2596951c6300SRichard Henderson { 2597951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i64) { 2598951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); 2599951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i64) { 26005dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2601951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2602951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2); 2603951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 2604951c6300SRichard Henderson tcg_temp_free_i64(t); 2605951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) { 26065dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 26075dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 26085dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 26095dd48602SRichard Henderson TCGv_i64 t3 = tcg_temp_ebb_new_i64(); 2610951c6300SRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 2611951c6300SRichard Henderson /* Adjust for negative inputs. */ 2612951c6300SRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 2613951c6300SRichard Henderson tcg_gen_sari_i64(t3, arg2, 63); 2614951c6300SRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 2615951c6300SRichard Henderson tcg_gen_and_i64(t3, t3, arg1); 2616951c6300SRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 2617951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t3); 2618951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2619951c6300SRichard Henderson tcg_temp_free_i64(t0); 2620951c6300SRichard Henderson tcg_temp_free_i64(t1); 2621951c6300SRichard Henderson tcg_temp_free_i64(t2); 2622951c6300SRichard Henderson tcg_temp_free_i64(t3); 2623951c6300SRichard Henderson } else { 26245dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2625951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 2626951c6300SRichard Henderson gen_helper_mulsh_i64(rh, arg1, arg2); 2627951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2628951c6300SRichard Henderson tcg_temp_free_i64(t0); 2629951c6300SRichard Henderson } 2630951c6300SRichard Henderson } 2631951c6300SRichard Henderson 26325087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 26335087abfbSRichard Henderson { 26345dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 26355dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 26365dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 26375087abfbSRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 26385087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 26395087abfbSRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 26405087abfbSRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 26415087abfbSRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 26425087abfbSRichard Henderson tcg_gen_mov_i64(rl, t0); 26435087abfbSRichard Henderson tcg_temp_free_i64(t0); 26445087abfbSRichard Henderson tcg_temp_free_i64(t1); 26455087abfbSRichard Henderson tcg_temp_free_i64(t2); 26465087abfbSRichard Henderson } 26475087abfbSRichard Henderson 2648b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2649b87fb8cdSRichard Henderson { 2650b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); 2651b87fb8cdSRichard Henderson } 2652b87fb8cdSRichard Henderson 2653b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2654b87fb8cdSRichard Henderson { 2655b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); 2656b87fb8cdSRichard Henderson } 2657b87fb8cdSRichard Henderson 2658b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2659b87fb8cdSRichard Henderson { 2660b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); 2661b87fb8cdSRichard Henderson } 2662b87fb8cdSRichard Henderson 2663b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2664b87fb8cdSRichard Henderson { 2665b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); 2666b87fb8cdSRichard Henderson } 2667b87fb8cdSRichard Henderson 2668ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a) 2669ff1f11f7SRichard Henderson { 26705dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2671ff1f11f7SRichard Henderson 2672ff1f11f7SRichard Henderson tcg_gen_sari_i64(t, a, 63); 2673ff1f11f7SRichard Henderson tcg_gen_xor_i64(ret, a, t); 2674ff1f11f7SRichard Henderson tcg_gen_sub_i64(ret, ret, t); 2675ff1f11f7SRichard Henderson tcg_temp_free_i64(t); 2676ff1f11f7SRichard Henderson } 2677ff1f11f7SRichard Henderson 2678951c6300SRichard Henderson /* Size changing operations. */ 2679951c6300SRichard Henderson 2680609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2681951c6300SRichard Henderson { 26823a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2683951c6300SRichard Henderson tcg_gen_mov_i32(ret, TCGV_LOW(arg)); 2684609ad705SRichard Henderson } else if (TCG_TARGET_HAS_extrl_i64_i32) { 2685b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrl_i64_i32, 2686ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2687951c6300SRichard Henderson } else { 2688dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)arg); 2689609ad705SRichard Henderson } 2690609ad705SRichard Henderson } 2691609ad705SRichard Henderson 2692609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2693609ad705SRichard Henderson { 2694609ad705SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2695609ad705SRichard Henderson tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); 2696609ad705SRichard Henderson } else if (TCG_TARGET_HAS_extrh_i64_i32) { 2697b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrh_i64_i32, 2698ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2699951c6300SRichard Henderson } else { 27005dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2701609ad705SRichard Henderson tcg_gen_shri_i64(t, arg, 32); 2702dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)t); 2703951c6300SRichard Henderson tcg_temp_free_i64(t); 2704951c6300SRichard Henderson } 2705951c6300SRichard Henderson } 2706951c6300SRichard Henderson 2707951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2708951c6300SRichard Henderson { 27093a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2710951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2711951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 27123a13c3f3SRichard Henderson } else { 2713b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extu_i32_i64, 2714ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 27153a13c3f3SRichard Henderson } 2716951c6300SRichard Henderson } 2717951c6300SRichard Henderson 2718951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2719951c6300SRichard Henderson { 27203a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2721951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2722951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 27233a13c3f3SRichard Henderson } else { 2724b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_ext_i32_i64, 2725ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 27263a13c3f3SRichard Henderson } 2727951c6300SRichard Henderson } 2728951c6300SRichard Henderson 2729951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) 2730951c6300SRichard Henderson { 27313a13c3f3SRichard Henderson TCGv_i64 tmp; 27323a13c3f3SRichard Henderson 27333a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2734951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(dest), low); 2735951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(dest), high); 27363a13c3f3SRichard Henderson return; 27373a13c3f3SRichard Henderson } 27383a13c3f3SRichard Henderson 27395dd48602SRichard Henderson tmp = tcg_temp_ebb_new_i64(); 2740951c6300SRichard Henderson /* These extensions are only needed for type correctness. 2741951c6300SRichard Henderson We may be able to do better given target specific information. */ 2742951c6300SRichard Henderson tcg_gen_extu_i32_i64(tmp, high); 2743951c6300SRichard Henderson tcg_gen_extu_i32_i64(dest, low); 2744951c6300SRichard Henderson /* If deposit is available, use it. Otherwise use the extra 2745951c6300SRichard Henderson knowledge that we have of the zero-extensions above. */ 2746951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { 2747951c6300SRichard Henderson tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); 2748951c6300SRichard Henderson } else { 2749951c6300SRichard Henderson tcg_gen_shli_i64(tmp, tmp, 32); 2750951c6300SRichard Henderson tcg_gen_or_i64(dest, dest, tmp); 2751951c6300SRichard Henderson } 2752951c6300SRichard Henderson tcg_temp_free_i64(tmp); 2753951c6300SRichard Henderson } 2754951c6300SRichard Henderson 2755951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg) 2756951c6300SRichard Henderson { 27573a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2758951c6300SRichard Henderson tcg_gen_mov_i32(lo, TCGV_LOW(arg)); 2759951c6300SRichard Henderson tcg_gen_mov_i32(hi, TCGV_HIGH(arg)); 27603a13c3f3SRichard Henderson } else { 2761609ad705SRichard Henderson tcg_gen_extrl_i64_i32(lo, arg); 2762609ad705SRichard Henderson tcg_gen_extrh_i64_i32(hi, arg); 27633a13c3f3SRichard Henderson } 2764951c6300SRichard Henderson } 2765951c6300SRichard Henderson 2766951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) 2767951c6300SRichard Henderson { 2768951c6300SRichard Henderson tcg_gen_ext32u_i64(lo, arg); 2769951c6300SRichard Henderson tcg_gen_shri_i64(hi, arg, 32); 2770951c6300SRichard Henderson } 2771951c6300SRichard Henderson 27724771e71cSRichard Henderson void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg) 27734771e71cSRichard Henderson { 27744771e71cSRichard Henderson tcg_gen_mov_i64(lo, TCGV128_LOW(arg)); 27754771e71cSRichard Henderson tcg_gen_mov_i64(hi, TCGV128_HIGH(arg)); 27764771e71cSRichard Henderson } 27774771e71cSRichard Henderson 27784771e71cSRichard Henderson void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi) 27794771e71cSRichard Henderson { 27804771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_LOW(ret), lo); 27814771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_HIGH(ret), hi); 27824771e71cSRichard Henderson } 27834771e71cSRichard Henderson 27844771e71cSRichard Henderson void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src) 27854771e71cSRichard Henderson { 27864771e71cSRichard Henderson if (dst != src) { 27874771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src)); 27884771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src)); 27894771e71cSRichard Henderson } 27904771e71cSRichard Henderson } 27914771e71cSRichard Henderson 2792951c6300SRichard Henderson /* QEMU specific operations. */ 2793951c6300SRichard Henderson 2794d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx) 279507ea28b4SRichard Henderson { 2796eba40358SRichard Henderson /* 2797eba40358SRichard Henderson * Let the jit code return the read-only version of the 2798eba40358SRichard Henderson * TranslationBlock, so that we minimize the pc-relative 2799eba40358SRichard Henderson * distance of the address of the exit_tb code to TB. 2800eba40358SRichard Henderson * This will improve utilization of pc-relative address loads. 2801eba40358SRichard Henderson * 2802eba40358SRichard Henderson * TODO: Move this to translator_loop, so that all const 2803eba40358SRichard Henderson * TranslationBlock pointers refer to read-only memory. 2804eba40358SRichard Henderson * This requires coordination with targets that do not use 2805eba40358SRichard Henderson * the translator_loop. 2806eba40358SRichard Henderson */ 2807eba40358SRichard Henderson uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx; 280807ea28b4SRichard Henderson 280907ea28b4SRichard Henderson if (tb == NULL) { 281007ea28b4SRichard Henderson tcg_debug_assert(idx == 0); 281107ea28b4SRichard Henderson } else if (idx <= TB_EXIT_IDXMAX) { 281207ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG 281307ea28b4SRichard Henderson /* This is an exit following a goto_tb. Verify that we have 281407ea28b4SRichard Henderson seen this numbered exit before, via tcg_gen_goto_tb. */ 281507ea28b4SRichard Henderson tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); 281607ea28b4SRichard Henderson #endif 281707ea28b4SRichard Henderson } else { 281807ea28b4SRichard Henderson /* This is an exit via the exitreq label. */ 281907ea28b4SRichard Henderson tcg_debug_assert(idx == TB_EXIT_REQUESTED); 282007ea28b4SRichard Henderson } 282107ea28b4SRichard Henderson 282207ea28b4SRichard Henderson tcg_gen_op1i(INDEX_op_exit_tb, val); 282307ea28b4SRichard Henderson } 282407ea28b4SRichard Henderson 2825951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx) 2826951c6300SRichard Henderson { 282784f15616SRichard Henderson /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */ 2828b7e4afbdSRichard Henderson tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB)); 2829951c6300SRichard Henderson /* We only support two chained exits. */ 283007ea28b4SRichard Henderson tcg_debug_assert(idx <= TB_EXIT_IDXMAX); 2831951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG 2832a4761232SPhilippe Mathieu-Daudé /* Verify that we haven't seen this numbered exit before. */ 2833b1311c4aSEmilio G. Cota tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0); 2834b1311c4aSEmilio G. Cota tcg_ctx->goto_tb_issue_mask |= 1 << idx; 2835951c6300SRichard Henderson #endif 2836e6d86bedSEmilio G. Cota plugin_gen_disable_mem_helpers(); 2837951c6300SRichard Henderson tcg_gen_op1i(INDEX_op_goto_tb, idx); 2838951c6300SRichard Henderson } 2839951c6300SRichard Henderson 28407f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void) 2841cedbcb01SEmilio G. Cota { 2842e6d86bedSEmilio G. Cota TCGv_ptr ptr; 2843e6d86bedSEmilio G. Cota 2844b7e4afbdSRichard Henderson if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) { 284584f15616SRichard Henderson tcg_gen_exit_tb(NULL, 0); 284684f15616SRichard Henderson return; 284784f15616SRichard Henderson } 284884f15616SRichard Henderson 2849e6d86bedSEmilio G. Cota plugin_gen_disable_mem_helpers(); 28505dd48602SRichard Henderson ptr = tcg_temp_ebb_new_ptr(); 28511c2adb95SRichard Henderson gen_helper_lookup_tb_ptr(ptr, cpu_env); 2852ae8b75dcSRichard Henderson tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr)); 2853cedbcb01SEmilio G. Cota tcg_temp_free_ptr(ptr); 2854cedbcb01SEmilio G. Cota } 2855