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 { 105c914d46dSRichard Henderson #ifdef CONFIG_USER_ONLY 106c914d46dSRichard Henderson bool parallel = tcg_ctx->gen_tb->cflags & CF_PARALLEL; 107c914d46dSRichard Henderson #else 108c914d46dSRichard Henderson /* 109c914d46dSRichard Henderson * It is tempting to elide the barrier in a uniprocessor context. 110c914d46dSRichard Henderson * However, even with a single cpu we have i/o threads running in 111c914d46dSRichard Henderson * parallel, and lack of memory order can result in e.g. virtio 112c914d46dSRichard Henderson * queue entries being read incorrectly. 113c914d46dSRichard Henderson */ 114c914d46dSRichard Henderson bool parallel = true; 115c914d46dSRichard Henderson #endif 116c914d46dSRichard Henderson 117c914d46dSRichard 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 2793635502dSRichard Henderson void tcg_gen_negsetcond_i32(TCGCond cond, TCGv_i32 ret, 2803635502dSRichard Henderson TCGv_i32 arg1, TCGv_i32 arg2) 2813635502dSRichard Henderson { 2823635502dSRichard Henderson if (cond == TCG_COND_ALWAYS) { 2833635502dSRichard Henderson tcg_gen_movi_i32(ret, -1); 2843635502dSRichard Henderson } else if (cond == TCG_COND_NEVER) { 2853635502dSRichard Henderson tcg_gen_movi_i32(ret, 0); 2863635502dSRichard Henderson } else if (TCG_TARGET_HAS_negsetcond_i32) { 2873635502dSRichard Henderson tcg_gen_op4i_i32(INDEX_op_negsetcond_i32, ret, arg1, arg2, cond); 2883635502dSRichard Henderson } else { 2893635502dSRichard Henderson tcg_gen_setcond_i32(cond, ret, arg1, arg2); 2903635502dSRichard Henderson tcg_gen_neg_i32(ret, ret); 2913635502dSRichard Henderson } 2923635502dSRichard Henderson } 2933635502dSRichard Henderson 294951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 295951c6300SRichard Henderson { 296b2e3ae94SRichard Henderson if (arg2 == 0) { 297b2e3ae94SRichard Henderson tcg_gen_movi_i32(ret, 0); 298b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 299b2e3ae94SRichard Henderson tcg_gen_shli_i32(ret, arg1, ctz32(arg2)); 300b2e3ae94SRichard Henderson } else { 30111d11d61SRichard Henderson tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2)); 302951c6300SRichard Henderson } 303b2e3ae94SRichard Henderson } 304951c6300SRichard Henderson 305951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 306951c6300SRichard Henderson { 307951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 308951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2); 309951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3105dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 311951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 312951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2); 313951c6300SRichard Henderson tcg_temp_free_i32(t0); 314951c6300SRichard Henderson } else { 315951c6300SRichard Henderson gen_helper_div_i32(ret, arg1, arg2); 316951c6300SRichard Henderson } 317951c6300SRichard Henderson } 318951c6300SRichard Henderson 319951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 320951c6300SRichard Henderson { 321951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 322951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2); 323951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 3245dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 325951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2); 326951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 327951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 328951c6300SRichard Henderson tcg_temp_free_i32(t0); 329951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3305dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 331951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 332951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2); 333951c6300SRichard Henderson tcg_temp_free_i32(t0); 334951c6300SRichard Henderson } else { 335951c6300SRichard Henderson gen_helper_rem_i32(ret, arg1, arg2); 336951c6300SRichard Henderson } 337951c6300SRichard Henderson } 338951c6300SRichard Henderson 339951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 340951c6300SRichard Henderson { 341951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 342951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2); 343951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3445dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 345bfefdbeaSRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 346bfefdbeaSRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, zero, arg2); 347951c6300SRichard Henderson tcg_temp_free_i32(t0); 348951c6300SRichard Henderson } else { 349951c6300SRichard Henderson gen_helper_divu_i32(ret, arg1, arg2); 350951c6300SRichard Henderson } 351951c6300SRichard Henderson } 352951c6300SRichard Henderson 353951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 354951c6300SRichard Henderson { 355951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 356951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); 357951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 3585dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 359951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2); 360951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 361951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 362951c6300SRichard Henderson tcg_temp_free_i32(t0); 363951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 3645dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 365bfefdbeaSRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 366bfefdbeaSRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, zero, arg2); 367951c6300SRichard Henderson tcg_temp_free_i32(t0); 368951c6300SRichard Henderson } else { 369951c6300SRichard Henderson gen_helper_remu_i32(ret, arg1, arg2); 370951c6300SRichard Henderson } 371951c6300SRichard Henderson } 372951c6300SRichard Henderson 373951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 374951c6300SRichard Henderson { 375951c6300SRichard Henderson if (TCG_TARGET_HAS_andc_i32) { 376951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2); 377951c6300SRichard Henderson } else { 3785dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 379951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 380951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, t0); 381951c6300SRichard Henderson tcg_temp_free_i32(t0); 382951c6300SRichard Henderson } 383951c6300SRichard Henderson } 384951c6300SRichard Henderson 385951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 386951c6300SRichard Henderson { 387951c6300SRichard Henderson if (TCG_TARGET_HAS_eqv_i32) { 388951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2); 389951c6300SRichard Henderson } else { 390951c6300SRichard Henderson tcg_gen_xor_i32(ret, arg1, arg2); 391951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 392951c6300SRichard Henderson } 393951c6300SRichard Henderson } 394951c6300SRichard Henderson 395951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 396951c6300SRichard Henderson { 397951c6300SRichard Henderson if (TCG_TARGET_HAS_nand_i32) { 398951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2); 399951c6300SRichard Henderson } else { 400951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, arg2); 401951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 402951c6300SRichard Henderson } 403951c6300SRichard Henderson } 404951c6300SRichard Henderson 405951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 406951c6300SRichard Henderson { 407951c6300SRichard Henderson if (TCG_TARGET_HAS_nor_i32) { 408951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2); 409951c6300SRichard Henderson } else { 410951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, arg2); 411951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 412951c6300SRichard Henderson } 413951c6300SRichard Henderson } 414951c6300SRichard Henderson 415951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 416951c6300SRichard Henderson { 417951c6300SRichard Henderson if (TCG_TARGET_HAS_orc_i32) { 418951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2); 419951c6300SRichard Henderson } else { 4205dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 421951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 422951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, t0); 423951c6300SRichard Henderson tcg_temp_free_i32(t0); 424951c6300SRichard Henderson } 425951c6300SRichard Henderson } 426951c6300SRichard Henderson 4270e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 4280e28d006SRichard Henderson { 4290e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 4300e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2); 4310e28d006SRichard Henderson } else if (TCG_TARGET_HAS_clz_i64) { 4325dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 4335dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 4340e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 4350e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 4360e28d006SRichard Henderson tcg_gen_addi_i64(t2, t2, 32); 4370e28d006SRichard Henderson tcg_gen_clz_i64(t1, t1, t2); 4380e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 4390e28d006SRichard Henderson tcg_temp_free_i64(t1); 4400e28d006SRichard Henderson tcg_temp_free_i64(t2); 4410e28d006SRichard Henderson tcg_gen_subi_i32(ret, ret, 32); 4420e28d006SRichard Henderson } else { 4430e28d006SRichard Henderson gen_helper_clz_i32(ret, arg1, arg2); 4440e28d006SRichard Henderson } 4450e28d006SRichard Henderson } 4460e28d006SRichard Henderson 4470e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 4480e28d006SRichard Henderson { 44911d11d61SRichard Henderson tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2)); 4500e28d006SRichard Henderson } 4510e28d006SRichard Henderson 4520e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 4530e28d006SRichard Henderson { 4540e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i32) { 4550e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2); 4560e28d006SRichard Henderson } else if (TCG_TARGET_HAS_ctz_i64) { 4575dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 4585dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 4590e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 4600e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 4610e28d006SRichard Henderson tcg_gen_ctz_i64(t1, t1, t2); 4620e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 4630e28d006SRichard Henderson tcg_temp_free_i64(t1); 4640e28d006SRichard Henderson tcg_temp_free_i64(t2); 46514e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i32 46614e99210SRichard Henderson || TCG_TARGET_HAS_ctpop_i64 46714e99210SRichard Henderson || TCG_TARGET_HAS_clz_i32 46814e99210SRichard Henderson || TCG_TARGET_HAS_clz_i64) { 4695dd48602SRichard Henderson TCGv_i32 z, t = tcg_temp_ebb_new_i32(); 47014e99210SRichard Henderson 47114e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) { 47214e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 47314e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 47414e99210SRichard Henderson tcg_gen_ctpop_i32(t, t); 47514e99210SRichard Henderson } else { 47614e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 32, don't fight it. */ 47714e99210SRichard Henderson tcg_gen_neg_i32(t, arg1); 47814e99210SRichard Henderson tcg_gen_and_i32(t, t, arg1); 47914e99210SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 48014e99210SRichard Henderson tcg_gen_xori_i32(t, t, 31); 48114e99210SRichard Henderson } 48211d11d61SRichard Henderson z = tcg_constant_i32(0); 48314e99210SRichard Henderson tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t); 48414e99210SRichard Henderson tcg_temp_free_i32(t); 4850e28d006SRichard Henderson } else { 4860e28d006SRichard Henderson gen_helper_ctz_i32(ret, arg1, arg2); 4870e28d006SRichard Henderson } 4880e28d006SRichard Henderson } 4890e28d006SRichard Henderson 4900e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 4910e28d006SRichard Henderson { 49214e99210SRichard Henderson if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) { 49314e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 4945dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 49514e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 49614e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 49714e99210SRichard Henderson tcg_gen_ctpop_i32(ret, t); 49814e99210SRichard Henderson tcg_temp_free_i32(t); 49914e99210SRichard Henderson } else { 50011d11d61SRichard Henderson tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2)); 5010e28d006SRichard Henderson } 50214e99210SRichard Henderson } 5030e28d006SRichard Henderson 504086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg) 505086920c2SRichard Henderson { 506086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 5075dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 508086920c2SRichard Henderson tcg_gen_sari_i32(t, arg, 31); 509086920c2SRichard Henderson tcg_gen_xor_i32(t, t, arg); 510086920c2SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 511086920c2SRichard Henderson tcg_gen_subi_i32(ret, t, 1); 512086920c2SRichard Henderson tcg_temp_free_i32(t); 513086920c2SRichard Henderson } else { 514086920c2SRichard Henderson gen_helper_clrsb_i32(ret, arg); 515086920c2SRichard Henderson } 516086920c2SRichard Henderson } 517086920c2SRichard Henderson 518a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1) 519a768e4e9SRichard Henderson { 520a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32) { 521a768e4e9SRichard Henderson tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1); 522a768e4e9SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64) { 5235dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 524a768e4e9SRichard Henderson tcg_gen_extu_i32_i64(t, arg1); 525a768e4e9SRichard Henderson tcg_gen_ctpop_i64(t, t); 526a768e4e9SRichard Henderson tcg_gen_extrl_i64_i32(ret, t); 527a768e4e9SRichard Henderson tcg_temp_free_i64(t); 528a768e4e9SRichard Henderson } else { 529a768e4e9SRichard Henderson gen_helper_ctpop_i32(ret, arg1); 530a768e4e9SRichard Henderson } 531a768e4e9SRichard Henderson } 532a768e4e9SRichard Henderson 533951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 534951c6300SRichard Henderson { 535951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 536951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2); 537951c6300SRichard Henderson } else { 538951c6300SRichard Henderson TCGv_i32 t0, t1; 539951c6300SRichard Henderson 5405dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 5415dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 542951c6300SRichard Henderson tcg_gen_shl_i32(t0, arg1, arg2); 543951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 544951c6300SRichard Henderson tcg_gen_shr_i32(t1, arg1, t1); 545951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 546951c6300SRichard Henderson tcg_temp_free_i32(t0); 547951c6300SRichard Henderson tcg_temp_free_i32(t1); 548951c6300SRichard Henderson } 549951c6300SRichard Henderson } 550951c6300SRichard Henderson 55107dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 552951c6300SRichard Henderson { 55307dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 554951c6300SRichard Henderson /* some cases can be optimized here */ 555951c6300SRichard Henderson if (arg2 == 0) { 556951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 557951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i32) { 55811d11d61SRichard Henderson tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2)); 559951c6300SRichard Henderson } else { 560951c6300SRichard Henderson TCGv_i32 t0, t1; 5615dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 5625dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 563951c6300SRichard Henderson tcg_gen_shli_i32(t0, arg1, arg2); 564951c6300SRichard Henderson tcg_gen_shri_i32(t1, arg1, 32 - arg2); 565951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 566951c6300SRichard Henderson tcg_temp_free_i32(t0); 567951c6300SRichard Henderson tcg_temp_free_i32(t1); 568951c6300SRichard Henderson } 569951c6300SRichard Henderson } 570951c6300SRichard Henderson 571951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 572951c6300SRichard Henderson { 573951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 574951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2); 575951c6300SRichard Henderson } else { 576951c6300SRichard Henderson TCGv_i32 t0, t1; 577951c6300SRichard Henderson 5785dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 5795dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 580951c6300SRichard Henderson tcg_gen_shr_i32(t0, arg1, arg2); 581951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 582951c6300SRichard Henderson tcg_gen_shl_i32(t1, arg1, t1); 583951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 584951c6300SRichard Henderson tcg_temp_free_i32(t0); 585951c6300SRichard Henderson tcg_temp_free_i32(t1); 586951c6300SRichard Henderson } 587951c6300SRichard Henderson } 588951c6300SRichard Henderson 58907dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 590951c6300SRichard Henderson { 59107dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 592951c6300SRichard Henderson /* some cases can be optimized here */ 593951c6300SRichard Henderson if (arg2 == 0) { 594951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 595951c6300SRichard Henderson } else { 596951c6300SRichard Henderson tcg_gen_rotli_i32(ret, arg1, 32 - arg2); 597951c6300SRichard Henderson } 598951c6300SRichard Henderson } 599951c6300SRichard Henderson 600951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, 601951c6300SRichard Henderson unsigned int ofs, unsigned int len) 602951c6300SRichard Henderson { 603951c6300SRichard Henderson uint32_t mask; 604951c6300SRichard Henderson TCGv_i32 t1; 605951c6300SRichard Henderson 606951c6300SRichard Henderson tcg_debug_assert(ofs < 32); 6070d0d309dSRichard Henderson tcg_debug_assert(len > 0); 608951c6300SRichard Henderson tcg_debug_assert(len <= 32); 609951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 32); 610951c6300SRichard Henderson 6110d0d309dSRichard Henderson if (len == 32) { 612951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg2); 613951c6300SRichard Henderson return; 614951c6300SRichard Henderson } 615951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) { 616951c6300SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); 617951c6300SRichard Henderson return; 618951c6300SRichard Henderson } 619951c6300SRichard Henderson 6205dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 621951c6300SRichard Henderson 622b0a60567SRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 623b0a60567SRichard Henderson if (ofs + len == 32) { 624b0a60567SRichard Henderson tcg_gen_shli_i32(t1, arg1, len); 625b0a60567SRichard Henderson tcg_gen_extract2_i32(ret, t1, arg2, len); 626b0a60567SRichard Henderson goto done; 627b0a60567SRichard Henderson } 628b0a60567SRichard Henderson if (ofs == 0) { 629b0a60567SRichard Henderson tcg_gen_extract2_i32(ret, arg1, arg2, len); 630b0a60567SRichard Henderson tcg_gen_rotli_i32(ret, ret, len); 631b0a60567SRichard Henderson goto done; 632b0a60567SRichard Henderson } 633b0a60567SRichard Henderson } 634b0a60567SRichard Henderson 635b0a60567SRichard Henderson mask = (1u << len) - 1; 636951c6300SRichard Henderson if (ofs + len < 32) { 637951c6300SRichard Henderson tcg_gen_andi_i32(t1, arg2, mask); 638951c6300SRichard Henderson tcg_gen_shli_i32(t1, t1, ofs); 639951c6300SRichard Henderson } else { 640951c6300SRichard Henderson tcg_gen_shli_i32(t1, arg2, ofs); 641951c6300SRichard Henderson } 642951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg1, ~(mask << ofs)); 643951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 644b0a60567SRichard Henderson done: 645951c6300SRichard Henderson tcg_temp_free_i32(t1); 646951c6300SRichard Henderson } 647951c6300SRichard Henderson 64807cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, 64907cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 65007cc68d5SRichard Henderson { 65107cc68d5SRichard Henderson tcg_debug_assert(ofs < 32); 65207cc68d5SRichard Henderson tcg_debug_assert(len > 0); 65307cc68d5SRichard Henderson tcg_debug_assert(len <= 32); 65407cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 32); 65507cc68d5SRichard Henderson 65607cc68d5SRichard Henderson if (ofs + len == 32) { 65707cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 65807cc68d5SRichard Henderson } else if (ofs == 0) { 65907cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 66007cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i32 66107cc68d5SRichard Henderson && TCG_TARGET_deposit_i32_valid(ofs, len)) { 66211d11d61SRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 66307cc68d5SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); 66407cc68d5SRichard Henderson } else { 66507cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 66607cc68d5SRichard Henderson which allows ARG to stay live. */ 66707cc68d5SRichard Henderson switch (len) { 66807cc68d5SRichard Henderson case 16: 66907cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 67007cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 67107cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 67207cc68d5SRichard Henderson return; 67307cc68d5SRichard Henderson } 67407cc68d5SRichard Henderson break; 67507cc68d5SRichard Henderson case 8: 67607cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 67707cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 67807cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 67907cc68d5SRichard Henderson return; 68007cc68d5SRichard Henderson } 68107cc68d5SRichard Henderson break; 68207cc68d5SRichard Henderson } 68307cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 68407cc68d5SRichard Henderson switch (ofs + len) { 68507cc68d5SRichard Henderson case 16: 68607cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 68707cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 68807cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, ret); 68907cc68d5SRichard Henderson return; 69007cc68d5SRichard Henderson } 69107cc68d5SRichard Henderson break; 69207cc68d5SRichard Henderson case 8: 69307cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 69407cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 69507cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, ret); 69607cc68d5SRichard Henderson return; 69707cc68d5SRichard Henderson } 69807cc68d5SRichard Henderson break; 69907cc68d5SRichard Henderson } 70007cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 70107cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 70207cc68d5SRichard Henderson } 70307cc68d5SRichard Henderson } 70407cc68d5SRichard Henderson 7057ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, 7067ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 7077ec8bab3SRichard Henderson { 7087ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 7097ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 7107ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 7117ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 7127ec8bab3SRichard Henderson 7137ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 7147ec8bab3SRichard Henderson if (ofs + len == 32) { 7157ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, 32 - len); 7167ec8bab3SRichard Henderson return; 7177ec8bab3SRichard Henderson } 7187ec8bab3SRichard Henderson if (ofs == 0) { 7197ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 7207ec8bab3SRichard Henderson return; 7217ec8bab3SRichard Henderson } 7227ec8bab3SRichard Henderson 7237ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i32 7247ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 7257ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len); 7267ec8bab3SRichard Henderson return; 7277ec8bab3SRichard Henderson } 7287ec8bab3SRichard Henderson 7297ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 7307ec8bab3SRichard Henderson switch (ofs + len) { 7317ec8bab3SRichard Henderson case 16: 7327ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 7337ec8bab3SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 7347ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 7357ec8bab3SRichard Henderson return; 7367ec8bab3SRichard Henderson } 7377ec8bab3SRichard Henderson break; 7387ec8bab3SRichard Henderson case 8: 7397ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 7407ec8bab3SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 7417ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 7427ec8bab3SRichard Henderson return; 7437ec8bab3SRichard Henderson } 7447ec8bab3SRichard Henderson break; 7457ec8bab3SRichard Henderson } 7467ec8bab3SRichard Henderson 7477ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 7487ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special case of 16, 7497ec8bab3SRichard Henderson so that we get ext8u, ext16u. */ 7507ec8bab3SRichard Henderson switch (len) { 7517ec8bab3SRichard Henderson case 1 ... 8: case 16: 7527ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 7537ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, ret, (1u << len) - 1); 7547ec8bab3SRichard Henderson break; 7557ec8bab3SRichard Henderson default: 7567ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 7577ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, 32 - len); 7587ec8bab3SRichard Henderson break; 7597ec8bab3SRichard Henderson } 7607ec8bab3SRichard Henderson } 7617ec8bab3SRichard Henderson 7627ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg, 7637ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 7647ec8bab3SRichard Henderson { 7657ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 7667ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 7677ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 7687ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 7697ec8bab3SRichard Henderson 7707ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 7717ec8bab3SRichard Henderson if (ofs + len == 32) { 7727ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, arg, 32 - len); 7737ec8bab3SRichard Henderson return; 7747ec8bab3SRichard Henderson } 7757ec8bab3SRichard Henderson if (ofs == 0) { 7767ec8bab3SRichard Henderson switch (len) { 7777ec8bab3SRichard Henderson case 16: 7787ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 7797ec8bab3SRichard Henderson return; 7807ec8bab3SRichard Henderson case 8: 7817ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 7827ec8bab3SRichard Henderson return; 7837ec8bab3SRichard Henderson } 7847ec8bab3SRichard Henderson } 7857ec8bab3SRichard Henderson 7867ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i32 7877ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 7887ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); 7897ec8bab3SRichard Henderson return; 7907ec8bab3SRichard Henderson } 7917ec8bab3SRichard Henderson 7927ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 7937ec8bab3SRichard Henderson switch (ofs + len) { 7947ec8bab3SRichard Henderson case 16: 7957ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 7967ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 7977ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 7987ec8bab3SRichard Henderson return; 7997ec8bab3SRichard Henderson } 8007ec8bab3SRichard Henderson break; 8017ec8bab3SRichard Henderson case 8: 8027ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 8037ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 8047ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 8057ec8bab3SRichard Henderson return; 8067ec8bab3SRichard Henderson } 8077ec8bab3SRichard Henderson break; 8087ec8bab3SRichard Henderson } 8097ec8bab3SRichard Henderson switch (len) { 8107ec8bab3SRichard Henderson case 16: 8117ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 8127ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 8137ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, ret); 8147ec8bab3SRichard Henderson return; 8157ec8bab3SRichard Henderson } 8167ec8bab3SRichard Henderson break; 8177ec8bab3SRichard Henderson case 8: 8187ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 8197ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 8207ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, ret); 8217ec8bab3SRichard Henderson return; 8227ec8bab3SRichard Henderson } 8237ec8bab3SRichard Henderson break; 8247ec8bab3SRichard Henderson } 8257ec8bab3SRichard Henderson 8267ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 8277ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, 32 - len); 8287ec8bab3SRichard Henderson } 8297ec8bab3SRichard Henderson 8302089fcc9SDavid Hildenbrand /* 8312089fcc9SDavid Hildenbrand * Extract 32-bits from a 64-bit input, ah:al, starting from ofs. 8322089fcc9SDavid Hildenbrand * Unlike tcg_gen_extract_i32 above, len is fixed at 32. 8332089fcc9SDavid Hildenbrand */ 8342089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah, 8352089fcc9SDavid Hildenbrand unsigned int ofs) 8362089fcc9SDavid Hildenbrand { 8372089fcc9SDavid Hildenbrand tcg_debug_assert(ofs <= 32); 8382089fcc9SDavid Hildenbrand if (ofs == 0) { 8392089fcc9SDavid Hildenbrand tcg_gen_mov_i32(ret, al); 8402089fcc9SDavid Hildenbrand } else if (ofs == 32) { 8412089fcc9SDavid Hildenbrand tcg_gen_mov_i32(ret, ah); 8422089fcc9SDavid Hildenbrand } else if (al == ah) { 8432089fcc9SDavid Hildenbrand tcg_gen_rotri_i32(ret, al, ofs); 844fce1296fSRichard Henderson } else if (TCG_TARGET_HAS_extract2_i32) { 845fce1296fSRichard Henderson tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs); 8462089fcc9SDavid Hildenbrand } else { 8475dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 8482089fcc9SDavid Hildenbrand tcg_gen_shri_i32(t0, al, ofs); 8492089fcc9SDavid Hildenbrand tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs); 8502089fcc9SDavid Hildenbrand tcg_temp_free_i32(t0); 8512089fcc9SDavid Hildenbrand } 8522089fcc9SDavid Hildenbrand } 8532089fcc9SDavid Hildenbrand 854951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, 855951c6300SRichard Henderson TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) 856951c6300SRichard Henderson { 85737ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 85837ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v1); 85937ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 86037ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v2); 86137ed3bf1SRichard Henderson } else if (TCG_TARGET_HAS_movcond_i32) { 862951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond); 863951c6300SRichard Henderson } else { 8645dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 8655dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 8664a883870SRichard Henderson tcg_gen_negsetcond_i32(cond, t0, c1, c2); 867951c6300SRichard Henderson tcg_gen_and_i32(t1, v1, t0); 868951c6300SRichard Henderson tcg_gen_andc_i32(ret, v2, t0); 869951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 870951c6300SRichard Henderson tcg_temp_free_i32(t0); 871951c6300SRichard Henderson tcg_temp_free_i32(t1); 872951c6300SRichard Henderson } 873951c6300SRichard Henderson } 874951c6300SRichard Henderson 875951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 876951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 877951c6300SRichard Henderson { 878951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i32) { 879951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh); 880951c6300SRichard Henderson } else { 8815dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 8825dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 883951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 884951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 885951c6300SRichard Henderson tcg_gen_add_i64(t0, t0, t1); 886951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 887951c6300SRichard Henderson tcg_temp_free_i64(t0); 888951c6300SRichard Henderson tcg_temp_free_i64(t1); 889951c6300SRichard Henderson } 890951c6300SRichard Henderson } 891951c6300SRichard Henderson 892951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 893951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 894951c6300SRichard Henderson { 895951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i32) { 896951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh); 897951c6300SRichard Henderson } else { 8985dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 8995dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 900951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 901951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 902951c6300SRichard Henderson tcg_gen_sub_i64(t0, t0, t1); 903951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 904951c6300SRichard Henderson tcg_temp_free_i64(t0); 905951c6300SRichard Henderson tcg_temp_free_i64(t1); 906951c6300SRichard Henderson } 907951c6300SRichard Henderson } 908951c6300SRichard Henderson 909951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 910951c6300SRichard Henderson { 911951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i32) { 912951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); 913951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i32) { 9145dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 915951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 916951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2); 917951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 918951c6300SRichard Henderson tcg_temp_free_i32(t); 9199fd86b51SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 9205dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 9215dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 922951c6300SRichard Henderson tcg_gen_extu_i32_i64(t0, arg1); 923951c6300SRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 924951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 925951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 926951c6300SRichard Henderson tcg_temp_free_i64(t0); 927951c6300SRichard Henderson tcg_temp_free_i64(t1); 9289fd86b51SRichard Henderson } else { 9299fd86b51SRichard Henderson qemu_build_not_reached(); 930951c6300SRichard Henderson } 931951c6300SRichard Henderson } 932951c6300SRichard Henderson 933951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 934951c6300SRichard Henderson { 935951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i32) { 936951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); 937951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i32) { 9385dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 939951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 940951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2); 941951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 942951c6300SRichard Henderson tcg_temp_free_i32(t); 943951c6300SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 9445dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 9455dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 9465dd48602SRichard Henderson TCGv_i32 t2 = tcg_temp_ebb_new_i32(); 9475dd48602SRichard Henderson TCGv_i32 t3 = tcg_temp_ebb_new_i32(); 948951c6300SRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 949951c6300SRichard Henderson /* Adjust for negative inputs. */ 950951c6300SRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 951951c6300SRichard Henderson tcg_gen_sari_i32(t3, arg2, 31); 952951c6300SRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 953951c6300SRichard Henderson tcg_gen_and_i32(t3, t3, arg1); 954951c6300SRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 955951c6300SRichard Henderson tcg_gen_sub_i32(rh, rh, t3); 956951c6300SRichard Henderson tcg_gen_mov_i32(rl, t0); 957951c6300SRichard Henderson tcg_temp_free_i32(t0); 958951c6300SRichard Henderson tcg_temp_free_i32(t1); 959951c6300SRichard Henderson tcg_temp_free_i32(t2); 960951c6300SRichard Henderson tcg_temp_free_i32(t3); 961951c6300SRichard Henderson } else { 9625dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 9635dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 964951c6300SRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 965951c6300SRichard Henderson tcg_gen_ext_i32_i64(t1, arg2); 966951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 967951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 968951c6300SRichard Henderson tcg_temp_free_i64(t0); 969951c6300SRichard Henderson tcg_temp_free_i64(t1); 970951c6300SRichard Henderson } 971951c6300SRichard Henderson } 972951c6300SRichard Henderson 9735087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 9745087abfbSRichard Henderson { 9755087abfbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 9765dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 9775dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 9785dd48602SRichard Henderson TCGv_i32 t2 = tcg_temp_ebb_new_i32(); 9795087abfbSRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 9805087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 9815087abfbSRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 9825087abfbSRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 9835087abfbSRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 9845087abfbSRichard Henderson tcg_gen_mov_i32(rl, t0); 9855087abfbSRichard Henderson tcg_temp_free_i32(t0); 9865087abfbSRichard Henderson tcg_temp_free_i32(t1); 9875087abfbSRichard Henderson tcg_temp_free_i32(t2); 9885087abfbSRichard Henderson } else { 9895dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 9905dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 9915087abfbSRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 9925087abfbSRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 9935087abfbSRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 9945087abfbSRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 9955087abfbSRichard Henderson tcg_temp_free_i64(t0); 9965087abfbSRichard Henderson tcg_temp_free_i64(t1); 9975087abfbSRichard Henderson } 9985087abfbSRichard Henderson } 9995087abfbSRichard Henderson 1000951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg) 1001951c6300SRichard Henderson { 1002951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 1003951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg); 1004951c6300SRichard Henderson } else { 1005951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 24); 1006951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 24); 1007951c6300SRichard Henderson } 1008951c6300SRichard Henderson } 1009951c6300SRichard Henderson 1010951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg) 1011951c6300SRichard Henderson { 1012951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 1013951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg); 1014951c6300SRichard Henderson } else { 1015951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 16); 1016951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 16); 1017951c6300SRichard Henderson } 1018951c6300SRichard Henderson } 1019951c6300SRichard Henderson 1020951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg) 1021951c6300SRichard Henderson { 1022951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 1023951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg); 1024951c6300SRichard Henderson } else { 1025951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffu); 1026951c6300SRichard Henderson } 1027951c6300SRichard Henderson } 1028951c6300SRichard Henderson 1029951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg) 1030951c6300SRichard Henderson { 1031951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 1032951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg); 1033951c6300SRichard Henderson } else { 1034951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffffu); 1035951c6300SRichard Henderson } 1036951c6300SRichard Henderson } 1037951c6300SRichard Henderson 10384de5a76aSPhilippe Mathieu-Daudé /* 10394de5a76aSPhilippe Mathieu-Daudé * bswap16_i32: 16-bit byte swap on the low bits of a 32-bit value. 10404de5a76aSPhilippe Mathieu-Daudé * 10414de5a76aSPhilippe Mathieu-Daudé * Byte pattern: xxab -> yyba 10424de5a76aSPhilippe Mathieu-Daudé * 10434de5a76aSPhilippe Mathieu-Daudé * With TCG_BSWAP_IZ, x == zero, else undefined. 10444de5a76aSPhilippe Mathieu-Daudé * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined. 10454de5a76aSPhilippe Mathieu-Daudé */ 10462b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags) 1047951c6300SRichard Henderson { 10482b836c2aSRichard Henderson /* Only one extension flag may be present. */ 10492b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 10502b836c2aSRichard Henderson 1051951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap16_i32) { 10522b836c2aSRichard Henderson tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags); 1053951c6300SRichard Henderson } else { 10545dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 10555dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 1056951c6300SRichard Henderson 10574de5a76aSPhilippe Mathieu-Daudé /* arg = ..ab (IZ) xxab (!IZ) */ 10584de5a76aSPhilippe Mathieu-Daudé tcg_gen_shri_i32(t0, arg, 8); /* t0 = ...a (IZ) .xxa (!IZ) */ 10592b836c2aSRichard Henderson if (!(flags & TCG_BSWAP_IZ)) { 10604de5a76aSPhilippe Mathieu-Daudé tcg_gen_ext8u_i32(t0, t0); /* t0 = ...a */ 10612b836c2aSRichard Henderson } 10622b836c2aSRichard Henderson 10632b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 10644de5a76aSPhilippe Mathieu-Daudé tcg_gen_shli_i32(t1, arg, 24); /* t1 = b... */ 10654de5a76aSPhilippe Mathieu-Daudé tcg_gen_sari_i32(t1, t1, 16); /* t1 = ssb. */ 10662b836c2aSRichard Henderson } else if (flags & TCG_BSWAP_OZ) { 10674de5a76aSPhilippe Mathieu-Daudé tcg_gen_ext8u_i32(t1, arg); /* t1 = ...b */ 10684de5a76aSPhilippe Mathieu-Daudé tcg_gen_shli_i32(t1, t1, 8); /* t1 = ..b. */ 10692b836c2aSRichard Henderson } else { 10704de5a76aSPhilippe Mathieu-Daudé tcg_gen_shli_i32(t1, arg, 8); /* t1 = xab. */ 10712b836c2aSRichard Henderson } 10722b836c2aSRichard Henderson 10734de5a76aSPhilippe Mathieu-Daudé tcg_gen_or_i32(ret, t0, t1); /* ret = ..ba (OZ) */ 10744de5a76aSPhilippe Mathieu-Daudé /* = ssba (OS) */ 10754de5a76aSPhilippe Mathieu-Daudé /* = xaba (no flag) */ 1076951c6300SRichard Henderson tcg_temp_free_i32(t0); 10772b836c2aSRichard Henderson tcg_temp_free_i32(t1); 1078951c6300SRichard Henderson } 1079951c6300SRichard Henderson } 1080951c6300SRichard Henderson 108192964556SPhilippe Mathieu-Daudé /* 108292964556SPhilippe Mathieu-Daudé * bswap32_i32: 32-bit byte swap on a 32-bit value. 108392964556SPhilippe Mathieu-Daudé * 108492964556SPhilippe Mathieu-Daudé * Byte pattern: abcd -> dcba 108592964556SPhilippe Mathieu-Daudé */ 1086951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg) 1087951c6300SRichard Henderson { 1088951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap32_i32) { 1089587195bdSRichard Henderson tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0); 1090951c6300SRichard Henderson } else { 10915dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 10925dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 109311d11d61SRichard Henderson TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff); 1094951c6300SRichard Henderson 1095a686dc71SRichard Henderson /* arg = abcd */ 1096a686dc71SRichard Henderson tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */ 1097a686dc71SRichard Henderson tcg_gen_and_i32(t1, arg, t2); /* t1 = .b.d */ 1098a686dc71SRichard Henderson tcg_gen_and_i32(t0, t0, t2); /* t0 = .a.c */ 1099a686dc71SRichard Henderson tcg_gen_shli_i32(t1, t1, 8); /* t1 = b.d. */ 1100a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = badc */ 1101951c6300SRichard Henderson 1102a686dc71SRichard Henderson tcg_gen_shri_i32(t0, ret, 16); /* t0 = ..ba */ 1103a686dc71SRichard Henderson tcg_gen_shli_i32(t1, ret, 16); /* t1 = dc.. */ 1104a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = dcba */ 1105951c6300SRichard Henderson 1106951c6300SRichard Henderson tcg_temp_free_i32(t0); 1107951c6300SRichard Henderson tcg_temp_free_i32(t1); 1108951c6300SRichard Henderson } 1109951c6300SRichard Henderson } 1110951c6300SRichard Henderson 1111b8976aa5SPhilippe Mathieu-Daudé /* 1112b8976aa5SPhilippe Mathieu-Daudé * hswap_i32: Swap 16-bit halfwords within a 32-bit value. 1113b8976aa5SPhilippe Mathieu-Daudé * 1114b8976aa5SPhilippe Mathieu-Daudé * Byte pattern: abcd -> cdab 1115b8976aa5SPhilippe Mathieu-Daudé */ 111646be8425SRichard Henderson void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg) 111746be8425SRichard Henderson { 111846be8425SRichard Henderson /* Swapping 2 16-bit elements is a rotate. */ 111946be8425SRichard Henderson tcg_gen_rotli_i32(ret, arg, 16); 112046be8425SRichard Henderson } 112146be8425SRichard Henderson 1122b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1123b87fb8cdSRichard Henderson { 1124b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); 1125b87fb8cdSRichard Henderson } 1126b87fb8cdSRichard Henderson 1127b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1128b87fb8cdSRichard Henderson { 1129b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); 1130b87fb8cdSRichard Henderson } 1131b87fb8cdSRichard Henderson 1132b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1133b87fb8cdSRichard Henderson { 1134b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); 1135b87fb8cdSRichard Henderson } 1136b87fb8cdSRichard Henderson 1137b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1138b87fb8cdSRichard Henderson { 1139b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); 1140b87fb8cdSRichard Henderson } 1141b87fb8cdSRichard Henderson 1142ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a) 1143ff1f11f7SRichard Henderson { 11445dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 1145ff1f11f7SRichard Henderson 1146ff1f11f7SRichard Henderson tcg_gen_sari_i32(t, a, 31); 1147ff1f11f7SRichard Henderson tcg_gen_xor_i32(ret, a, t); 1148ff1f11f7SRichard Henderson tcg_gen_sub_i32(ret, ret, t); 1149ff1f11f7SRichard Henderson tcg_temp_free_i32(t); 1150ff1f11f7SRichard Henderson } 1151ff1f11f7SRichard Henderson 1152951c6300SRichard Henderson /* 64-bit ops */ 1153951c6300SRichard Henderson 1154951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32 1155951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64. */ 1156951c6300SRichard Henderson 1157951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg) 1158951c6300SRichard Henderson { 1159951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_LOW(arg)); 1160951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_HIGH(arg)); 1161951c6300SRichard Henderson } 1162951c6300SRichard Henderson 1163951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg) 1164951c6300SRichard Henderson { 116511d11d61SRichard Henderson TCGTemp *ts = tcgv_i64_temp(arg); 116611d11d61SRichard Henderson 116711d11d61SRichard Henderson /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */ 116811d11d61SRichard Henderson if (ts->kind == TEMP_CONST) { 116911d11d61SRichard Henderson tcg_gen_movi_i64(ret, ts->val); 117011d11d61SRichard Henderson } else { 1171951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1172951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 1173951c6300SRichard Henderson } 117411d11d61SRichard Henderson } 1175951c6300SRichard Henderson 1176951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 1177951c6300SRichard Henderson { 1178951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), arg); 1179951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32); 1180951c6300SRichard Henderson } 1181951c6300SRichard Henderson 1182951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1183951c6300SRichard Henderson { 1184951c6300SRichard Henderson tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset); 1185951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1186951c6300SRichard Henderson } 1187951c6300SRichard Henderson 1188951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1189951c6300SRichard Henderson { 1190951c6300SRichard Henderson tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset); 11913ff91d7eSJoseph Myers tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1192951c6300SRichard Henderson } 1193951c6300SRichard Henderson 1194951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1195951c6300SRichard Henderson { 1196951c6300SRichard Henderson tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset); 1197951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1198951c6300SRichard Henderson } 1199951c6300SRichard Henderson 1200951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1201951c6300SRichard Henderson { 1202951c6300SRichard Henderson tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset); 1203951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1204951c6300SRichard Henderson } 1205951c6300SRichard Henderson 1206951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1207951c6300SRichard Henderson { 1208951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1209951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1210951c6300SRichard Henderson } 1211951c6300SRichard Henderson 1212951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1213951c6300SRichard Henderson { 1214951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1215951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1216951c6300SRichard Henderson } 1217951c6300SRichard Henderson 1218951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1219951c6300SRichard Henderson { 1220951c6300SRichard Henderson /* Since arg2 and ret have different types, 1221951c6300SRichard Henderson they cannot be the same temporary */ 1222e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 1223951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset); 1224951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4); 1225951c6300SRichard Henderson #else 1226951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1227951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4); 1228951c6300SRichard Henderson #endif 1229951c6300SRichard Henderson } 1230951c6300SRichard Henderson 1231d56fea79SRichard Henderson void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1232d56fea79SRichard Henderson { 1233d56fea79SRichard Henderson tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset); 1234d56fea79SRichard Henderson } 1235d56fea79SRichard Henderson 1236d56fea79SRichard Henderson void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1237d56fea79SRichard Henderson { 1238d56fea79SRichard Henderson tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset); 1239d56fea79SRichard Henderson } 1240d56fea79SRichard Henderson 1241d56fea79SRichard Henderson void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1242d56fea79SRichard Henderson { 1243d56fea79SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1244d56fea79SRichard Henderson } 1245d56fea79SRichard Henderson 1246951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1247951c6300SRichard Henderson { 1248e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 1249951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset); 1250951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4); 1251951c6300SRichard Henderson #else 1252951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1253951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4); 1254951c6300SRichard Henderson #endif 1255951c6300SRichard Henderson } 1256951c6300SRichard Henderson 1257d56fea79SRichard Henderson void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1258d56fea79SRichard Henderson { 1259d56fea79SRichard Henderson tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1260d56fea79SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1261d56fea79SRichard Henderson } 1262d56fea79SRichard Henderson 1263d56fea79SRichard Henderson void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1264d56fea79SRichard Henderson { 1265d56fea79SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1266d56fea79SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1267d56fea79SRichard Henderson } 1268d56fea79SRichard Henderson 1269951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1270951c6300SRichard Henderson { 1271951c6300SRichard Henderson tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1272951c6300SRichard Henderson tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1273951c6300SRichard Henderson } 1274951c6300SRichard Henderson 1275951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1276951c6300SRichard Henderson { 1277951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1278951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1279951c6300SRichard Henderson } 1280951c6300SRichard Henderson 1281951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1282951c6300SRichard Henderson { 1283951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1284951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1285951c6300SRichard Henderson } 1286951c6300SRichard Henderson 1287951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1288951c6300SRichard Henderson { 1289951c6300SRichard Henderson gen_helper_shl_i64(ret, arg1, arg2); 1290951c6300SRichard Henderson } 1291951c6300SRichard Henderson 1292951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1293951c6300SRichard Henderson { 1294951c6300SRichard Henderson gen_helper_shr_i64(ret, arg1, arg2); 1295951c6300SRichard Henderson } 1296951c6300SRichard Henderson 1297951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1298951c6300SRichard Henderson { 1299951c6300SRichard Henderson gen_helper_sar_i64(ret, arg1, arg2); 1300951c6300SRichard Henderson } 1301951c6300SRichard Henderson 1302951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1303951c6300SRichard Henderson { 1304951c6300SRichard Henderson TCGv_i64 t0; 1305951c6300SRichard Henderson TCGv_i32 t1; 1306951c6300SRichard Henderson 13075dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 13085dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 1309951c6300SRichard Henderson 1310951c6300SRichard Henderson tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0), 1311951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_LOW(arg2)); 1312951c6300SRichard Henderson 1313951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); 1314951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1315951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2)); 1316951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1317951c6300SRichard Henderson 1318951c6300SRichard Henderson tcg_gen_mov_i64(ret, t0); 1319951c6300SRichard Henderson tcg_temp_free_i64(t0); 1320951c6300SRichard Henderson tcg_temp_free_i32(t1); 1321951c6300SRichard Henderson } 132211d11d61SRichard Henderson 132311d11d61SRichard Henderson #else 132411d11d61SRichard Henderson 132511d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 132611d11d61SRichard Henderson { 132711d11d61SRichard Henderson tcg_gen_mov_i64(ret, tcg_constant_i64(arg)); 132811d11d61SRichard Henderson } 132911d11d61SRichard Henderson 1330951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */ 1331951c6300SRichard Henderson 1332951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1333951c6300SRichard Henderson { 1334951c6300SRichard Henderson /* some cases can be optimized here */ 1335951c6300SRichard Henderson if (arg2 == 0) { 1336951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 133711d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 133811d11d61SRichard Henderson tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2)); 1339951c6300SRichard Henderson } else { 134011d11d61SRichard Henderson tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 134111d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 134211d11d61SRichard Henderson tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1343951c6300SRichard Henderson } 1344951c6300SRichard Henderson } 1345951c6300SRichard Henderson 1346951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2) 1347951c6300SRichard Henderson { 1348951c6300SRichard Henderson if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) { 1349951c6300SRichard Henderson /* Don't recurse with tcg_gen_neg_i64. */ 1350951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2); 135111d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 135211d11d61SRichard Henderson tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2); 1353951c6300SRichard Henderson } else { 135411d11d61SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 135511d11d61SRichard Henderson tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32), 135611d11d61SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1357951c6300SRichard Henderson } 1358951c6300SRichard Henderson } 1359951c6300SRichard Henderson 1360951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1361951c6300SRichard Henderson { 1362951c6300SRichard Henderson /* some cases can be optimized here */ 1363951c6300SRichard Henderson if (arg2 == 0) { 1364951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 136511d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 136611d11d61SRichard Henderson tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2)); 1367951c6300SRichard Henderson } else { 136811d11d61SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 136911d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 137011d11d61SRichard Henderson tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1371951c6300SRichard Henderson } 1372951c6300SRichard Henderson } 1373951c6300SRichard Henderson 1374474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1375951c6300SRichard Henderson { 13763a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1377951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1378951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 13793a13c3f3SRichard Henderson return; 13803a13c3f3SRichard Henderson } 13813a13c3f3SRichard Henderson 1382951c6300SRichard Henderson /* Some cases can be optimized here. */ 1383951c6300SRichard Henderson switch (arg2) { 1384951c6300SRichard Henderson case 0: 1385951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1386951c6300SRichard Henderson return; 1387474b2e8fSRichard Henderson case -1: 1388951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1389951c6300SRichard Henderson return; 1390474b2e8fSRichard Henderson case 0xff: 1391951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i64. */ 1392951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 1393951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1); 1394951c6300SRichard Henderson return; 1395951c6300SRichard Henderson } 1396951c6300SRichard Henderson break; 1397474b2e8fSRichard Henderson case 0xffff: 1398951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 1399951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1); 1400951c6300SRichard Henderson return; 1401951c6300SRichard Henderson } 1402951c6300SRichard Henderson break; 1403474b2e8fSRichard Henderson case 0xffffffffu: 1404951c6300SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 1405951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1); 1406951c6300SRichard Henderson return; 1407951c6300SRichard Henderson } 1408951c6300SRichard Henderson break; 1409951c6300SRichard Henderson } 141011d11d61SRichard Henderson 141111d11d61SRichard Henderson tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2)); 1412951c6300SRichard Henderson } 1413951c6300SRichard Henderson 1414951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1415951c6300SRichard Henderson { 14163a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1417951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1418951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 14193a13c3f3SRichard Henderson return; 14203a13c3f3SRichard Henderson } 1421951c6300SRichard Henderson /* Some cases can be optimized here. */ 1422951c6300SRichard Henderson if (arg2 == -1) { 1423951c6300SRichard Henderson tcg_gen_movi_i64(ret, -1); 1424951c6300SRichard Henderson } else if (arg2 == 0) { 1425951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1426951c6300SRichard Henderson } else { 142711d11d61SRichard Henderson tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2)); 1428951c6300SRichard Henderson } 1429951c6300SRichard Henderson } 1430951c6300SRichard Henderson 1431951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1432951c6300SRichard Henderson { 14333a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1434951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1435951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 14363a13c3f3SRichard Henderson return; 14373a13c3f3SRichard Henderson } 1438951c6300SRichard Henderson /* Some cases can be optimized here. */ 1439951c6300SRichard Henderson if (arg2 == 0) { 1440951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1441951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) { 1442951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i64. */ 1443951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1); 1444951c6300SRichard Henderson } else { 144511d11d61SRichard Henderson tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2)); 1446951c6300SRichard Henderson } 1447951c6300SRichard Henderson } 1448951c6300SRichard Henderson 1449951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, 1450951c6300SRichard Henderson unsigned c, bool right, bool arith) 1451951c6300SRichard Henderson { 1452951c6300SRichard Henderson tcg_debug_assert(c < 64); 1453951c6300SRichard Henderson if (c == 0) { 1454951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1455951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1456951c6300SRichard Henderson } else if (c >= 32) { 1457951c6300SRichard Henderson c -= 32; 1458951c6300SRichard Henderson if (right) { 1459951c6300SRichard Henderson if (arith) { 1460951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1461951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); 1462951c6300SRichard Henderson } else { 1463951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1464951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1465951c6300SRichard Henderson } 1466951c6300SRichard Henderson } else { 1467951c6300SRichard Henderson tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c); 1468951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 1469951c6300SRichard Henderson } 147002616badSRichard Henderson } else if (right) { 147102616badSRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 147202616badSRichard Henderson tcg_gen_extract2_i32(TCGV_LOW(ret), 147302616badSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), c); 1474951c6300SRichard Henderson } else { 1475951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 147602616badSRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret), 147702616badSRichard Henderson TCGV_HIGH(arg1), 32 - c, c); 1478951c6300SRichard Henderson } 147902616badSRichard Henderson if (arith) { 148002616badSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 148102616badSRichard Henderson } else { 148202616badSRichard Henderson tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 148302616badSRichard Henderson } 148402616badSRichard Henderson } else { 148502616badSRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 148602616badSRichard Henderson tcg_gen_extract2_i32(TCGV_HIGH(ret), 148702616badSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c); 148802616badSRichard Henderson } else { 14895dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 149002616badSRichard Henderson tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c); 149102616badSRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), t0, 149202616badSRichard Henderson TCGV_HIGH(arg1), c, 32 - c); 1493951c6300SRichard Henderson tcg_temp_free_i32(t0); 149402616badSRichard Henderson } 149502616badSRichard Henderson tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 1496951c6300SRichard Henderson } 1497951c6300SRichard Henderson } 1498951c6300SRichard Henderson 1499474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1500951c6300SRichard Henderson { 1501474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 15023a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 15033a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0); 15043a13c3f3SRichard Henderson } else if (arg2 == 0) { 1505951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1506951c6300SRichard Henderson } else { 150711d11d61SRichard Henderson tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2)); 1508951c6300SRichard Henderson } 1509951c6300SRichard Henderson } 1510951c6300SRichard Henderson 1511474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1512951c6300SRichard Henderson { 1513474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 15143a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 15153a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0); 15163a13c3f3SRichard Henderson } else if (arg2 == 0) { 1517951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1518951c6300SRichard Henderson } else { 151911d11d61SRichard Henderson tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2)); 1520951c6300SRichard Henderson } 1521951c6300SRichard Henderson } 1522951c6300SRichard Henderson 1523474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1524951c6300SRichard Henderson { 1525474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 15263a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 15273a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1); 15283a13c3f3SRichard Henderson } else if (arg2 == 0) { 1529951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1530951c6300SRichard Henderson } else { 153111d11d61SRichard Henderson tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2)); 1532951c6300SRichard Henderson } 1533951c6300SRichard Henderson } 1534951c6300SRichard Henderson 153542a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l) 1536951c6300SRichard Henderson { 1537951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 153842a268c2SRichard Henderson tcg_gen_br(l); 1539951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 15403a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1541951c6300SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1), 1542951c6300SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), 154342a268c2SRichard Henderson TCGV_HIGH(arg2), cond, label_arg(l)); 15443a13c3f3SRichard Henderson } else { 154542a268c2SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, 154642a268c2SRichard Henderson label_arg(l)); 15473a13c3f3SRichard Henderson } 1548f85b1fc4SRichard Henderson add_last_as_label_use(l); 1549951c6300SRichard Henderson } 1550951c6300SRichard Henderson } 1551951c6300SRichard Henderson 155242a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l) 1553951c6300SRichard Henderson { 155411d11d61SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 155511d11d61SRichard Henderson tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l); 155611d11d61SRichard Henderson } else if (cond == TCG_COND_ALWAYS) { 155742a268c2SRichard Henderson tcg_gen_br(l); 1558951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 155911d11d61SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, 156011d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 156111d11d61SRichard Henderson tcg_constant_i32(arg2), 156211d11d61SRichard Henderson tcg_constant_i32(arg2 >> 32), 156311d11d61SRichard Henderson cond, label_arg(l)); 1564f85b1fc4SRichard Henderson add_last_as_label_use(l); 1565951c6300SRichard Henderson } 1566951c6300SRichard Henderson } 1567951c6300SRichard Henderson 1568951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, 1569951c6300SRichard Henderson TCGv_i64 arg1, TCGv_i64 arg2) 1570951c6300SRichard Henderson { 1571951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 1572951c6300SRichard Henderson tcg_gen_movi_i64(ret, 1); 1573951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 1574951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1575951c6300SRichard Henderson } else { 15763a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1577951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 1578951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 1579951c6300SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 1580951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 15813a13c3f3SRichard Henderson } else { 1582951c6300SRichard Henderson tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); 15833a13c3f3SRichard Henderson } 1584951c6300SRichard Henderson } 1585951c6300SRichard Henderson } 1586951c6300SRichard Henderson 1587951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, 1588951c6300SRichard Henderson TCGv_i64 arg1, int64_t arg2) 1589951c6300SRichard Henderson { 159011d11d61SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 159111d11d61SRichard Henderson tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2)); 159211d11d61SRichard Henderson } else if (cond == TCG_COND_ALWAYS) { 159311d11d61SRichard Henderson tcg_gen_movi_i64(ret, 1); 159411d11d61SRichard Henderson } else if (cond == TCG_COND_NEVER) { 159511d11d61SRichard Henderson tcg_gen_movi_i64(ret, 0); 159611d11d61SRichard Henderson } else { 159711d11d61SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 159811d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 159911d11d61SRichard Henderson tcg_constant_i32(arg2), 160011d11d61SRichard Henderson tcg_constant_i32(arg2 >> 32), cond); 160111d11d61SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 160211d11d61SRichard Henderson } 1603951c6300SRichard Henderson } 1604951c6300SRichard Henderson 16053635502dSRichard Henderson void tcg_gen_negsetcond_i64(TCGCond cond, TCGv_i64 ret, 16063635502dSRichard Henderson TCGv_i64 arg1, TCGv_i64 arg2) 16073635502dSRichard Henderson { 16083635502dSRichard Henderson if (cond == TCG_COND_ALWAYS) { 16093635502dSRichard Henderson tcg_gen_movi_i64(ret, -1); 16103635502dSRichard Henderson } else if (cond == TCG_COND_NEVER) { 16113635502dSRichard Henderson tcg_gen_movi_i64(ret, 0); 16123635502dSRichard Henderson } else if (TCG_TARGET_HAS_negsetcond_i64) { 16133635502dSRichard Henderson tcg_gen_op4i_i64(INDEX_op_negsetcond_i64, ret, arg1, arg2, cond); 16143635502dSRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 16153635502dSRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 16163635502dSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 16173635502dSRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 16183635502dSRichard Henderson tcg_gen_neg_i32(TCGV_LOW(ret), TCGV_LOW(ret)); 16193635502dSRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_LOW(ret)); 16203635502dSRichard Henderson } else { 16213635502dSRichard Henderson tcg_gen_setcond_i64(cond, ret, arg1, arg2); 16223635502dSRichard Henderson tcg_gen_neg_i64(ret, ret); 16233635502dSRichard Henderson } 16243635502dSRichard Henderson } 16253635502dSRichard Henderson 1626951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1627951c6300SRichard Henderson { 1628b2e3ae94SRichard Henderson if (arg2 == 0) { 1629b2e3ae94SRichard Henderson tcg_gen_movi_i64(ret, 0); 1630b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 1631b2e3ae94SRichard Henderson tcg_gen_shli_i64(ret, arg1, ctz64(arg2)); 1632b2e3ae94SRichard Henderson } else { 1633f04de891SRichard Henderson tcg_gen_mul_i64(ret, arg1, tcg_constant_i64(arg2)); 1634951c6300SRichard Henderson } 1635b2e3ae94SRichard Henderson } 1636951c6300SRichard Henderson 1637951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1638951c6300SRichard Henderson { 1639951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 1640951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2); 1641951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16425dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1643951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 1644951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2); 1645951c6300SRichard Henderson tcg_temp_free_i64(t0); 1646951c6300SRichard Henderson } else { 1647951c6300SRichard Henderson gen_helper_div_i64(ret, arg1, arg2); 1648951c6300SRichard Henderson } 1649951c6300SRichard Henderson } 1650951c6300SRichard Henderson 1651951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1652951c6300SRichard Henderson { 1653951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 1654951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2); 1655951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 16565dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1657951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2); 1658951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 1659951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1660951c6300SRichard Henderson tcg_temp_free_i64(t0); 1661951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16625dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1663951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 1664951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2); 1665951c6300SRichard Henderson tcg_temp_free_i64(t0); 1666951c6300SRichard Henderson } else { 1667951c6300SRichard Henderson gen_helper_rem_i64(ret, arg1, arg2); 1668951c6300SRichard Henderson } 1669951c6300SRichard Henderson } 1670951c6300SRichard Henderson 1671951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1672951c6300SRichard Henderson { 1673951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 1674951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2); 1675951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16765dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1677bfefdbeaSRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 1678bfefdbeaSRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, zero, arg2); 1679951c6300SRichard Henderson tcg_temp_free_i64(t0); 1680951c6300SRichard Henderson } else { 1681951c6300SRichard Henderson gen_helper_divu_i64(ret, arg1, arg2); 1682951c6300SRichard Henderson } 1683951c6300SRichard Henderson } 1684951c6300SRichard Henderson 1685951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1686951c6300SRichard Henderson { 1687951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 1688951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); 1689951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 16905dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1691951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2); 1692951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 1693951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1694951c6300SRichard Henderson tcg_temp_free_i64(t0); 1695951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 16965dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1697bfefdbeaSRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 1698bfefdbeaSRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, zero, arg2); 1699951c6300SRichard Henderson tcg_temp_free_i64(t0); 1700951c6300SRichard Henderson } else { 1701951c6300SRichard Henderson gen_helper_remu_i64(ret, arg1, arg2); 1702951c6300SRichard Henderson } 1703951c6300SRichard Henderson } 1704951c6300SRichard Henderson 1705951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg) 1706951c6300SRichard Henderson { 17073a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1708951c6300SRichard Henderson tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1709951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 17103a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8s_i64) { 1711951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg); 1712951c6300SRichard Henderson } else { 1713951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 56); 1714951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 56); 1715951c6300SRichard Henderson } 1716951c6300SRichard Henderson } 1717951c6300SRichard Henderson 1718951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg) 1719951c6300SRichard Henderson { 17203a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1721951c6300SRichard Henderson tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1722951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 17233a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16s_i64) { 1724951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg); 1725951c6300SRichard Henderson } else { 1726951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 48); 1727951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 48); 1728951c6300SRichard Henderson } 1729951c6300SRichard Henderson } 1730951c6300SRichard Henderson 1731951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg) 1732951c6300SRichard Henderson { 17333a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1734951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1735951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 17363a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32s_i64) { 1737951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg); 1738951c6300SRichard Henderson } else { 1739951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 32); 1740951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 32); 1741951c6300SRichard Henderson } 1742951c6300SRichard Henderson } 1743951c6300SRichard Henderson 1744951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg) 1745951c6300SRichard Henderson { 17463a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1747951c6300SRichard Henderson tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1748951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17493a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8u_i64) { 1750951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg); 1751951c6300SRichard Henderson } else { 1752951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffu); 1753951c6300SRichard Henderson } 1754951c6300SRichard Henderson } 1755951c6300SRichard Henderson 1756951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg) 1757951c6300SRichard Henderson { 17583a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1759951c6300SRichard Henderson tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1760951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17613a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16u_i64) { 1762951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg); 1763951c6300SRichard Henderson } else { 1764951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffu); 1765951c6300SRichard Henderson } 1766951c6300SRichard Henderson } 1767951c6300SRichard Henderson 1768951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg) 1769951c6300SRichard Henderson { 17703a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1771951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1772951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17733a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32u_i64) { 1774951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg); 1775951c6300SRichard Henderson } else { 1776951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffffffu); 1777951c6300SRichard Henderson } 1778951c6300SRichard Henderson } 1779951c6300SRichard Henderson 17808b078800SPhilippe Mathieu-Daudé /* 17818b078800SPhilippe Mathieu-Daudé * bswap16_i64: 16-bit byte swap on the low bits of a 64-bit value. 17828b078800SPhilippe Mathieu-Daudé * 17838b078800SPhilippe Mathieu-Daudé * Byte pattern: xxxxxxxxab -> yyyyyyyyba 17848b078800SPhilippe Mathieu-Daudé * 17858b078800SPhilippe Mathieu-Daudé * With TCG_BSWAP_IZ, x == zero, else undefined. 17868b078800SPhilippe Mathieu-Daudé * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined. 17878b078800SPhilippe Mathieu-Daudé */ 17882b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 1789951c6300SRichard Henderson { 17902b836c2aSRichard Henderson /* Only one extension flag may be present. */ 17912b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 17922b836c2aSRichard Henderson 17933a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17942b836c2aSRichard Henderson tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags); 17952b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 17962b836c2aSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 17972b836c2aSRichard Henderson } else { 1798951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 17992b836c2aSRichard Henderson } 18003a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap16_i64) { 18012b836c2aSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags); 1802951c6300SRichard Henderson } else { 18035dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 18045dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 1805951c6300SRichard Henderson 18068b078800SPhilippe Mathieu-Daudé /* arg = ......ab or xxxxxxab */ 18078b078800SPhilippe Mathieu-Daudé tcg_gen_shri_i64(t0, arg, 8); /* t0 = .......a or .xxxxxxa */ 18082b836c2aSRichard Henderson if (!(flags & TCG_BSWAP_IZ)) { 18098b078800SPhilippe Mathieu-Daudé tcg_gen_ext8u_i64(t0, t0); /* t0 = .......a */ 18102b836c2aSRichard Henderson } 18112b836c2aSRichard Henderson 18122b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 18138b078800SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t1, arg, 56); /* t1 = b....... */ 18148b078800SPhilippe Mathieu-Daudé tcg_gen_sari_i64(t1, t1, 48); /* t1 = ssssssb. */ 18152b836c2aSRichard Henderson } else if (flags & TCG_BSWAP_OZ) { 18168b078800SPhilippe Mathieu-Daudé tcg_gen_ext8u_i64(t1, arg); /* t1 = .......b */ 18178b078800SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t1, t1, 8); /* t1 = ......b. */ 18182b836c2aSRichard Henderson } else { 18198b078800SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t1, arg, 8); /* t1 = xxxxxab. */ 18202b836c2aSRichard Henderson } 18212b836c2aSRichard Henderson 18228b078800SPhilippe Mathieu-Daudé tcg_gen_or_i64(ret, t0, t1); /* ret = ......ba (OZ) */ 18238b078800SPhilippe Mathieu-Daudé /* ssssssba (OS) */ 18248b078800SPhilippe Mathieu-Daudé /* xxxxxaba (no flag) */ 1825951c6300SRichard Henderson tcg_temp_free_i64(t0); 18262b836c2aSRichard Henderson tcg_temp_free_i64(t1); 1827951c6300SRichard Henderson } 1828951c6300SRichard Henderson } 1829951c6300SRichard Henderson 18309c406215SPhilippe Mathieu-Daudé /* 18319c406215SPhilippe Mathieu-Daudé * bswap32_i64: 32-bit byte swap on the low bits of a 64-bit value. 18329c406215SPhilippe Mathieu-Daudé * 18339c406215SPhilippe Mathieu-Daudé * Byte pattern: xxxxabcd -> yyyydcba 18349c406215SPhilippe Mathieu-Daudé * 18359c406215SPhilippe Mathieu-Daudé * With TCG_BSWAP_IZ, x == zero, else undefined. 18369c406215SPhilippe Mathieu-Daudé * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined. 18379c406215SPhilippe Mathieu-Daudé */ 18382b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 1839951c6300SRichard Henderson { 18402b836c2aSRichard Henderson /* Only one extension flag may be present. */ 18412b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 18422b836c2aSRichard Henderson 18433a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1844951c6300SRichard Henderson tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 18452b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 18462b836c2aSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 18472b836c2aSRichard Henderson } else { 1848951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 18492b836c2aSRichard Henderson } 18503a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap32_i64) { 18512b836c2aSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags); 1852951c6300SRichard Henderson } else { 18535dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 18545dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 185511d11d61SRichard Henderson TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff); 1856951c6300SRichard Henderson 18572b836c2aSRichard Henderson /* arg = xxxxabcd */ 18582b836c2aSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .xxxxabc */ 1859a686dc71SRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */ 1860a686dc71SRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */ 1861a686dc71SRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */ 1862a686dc71SRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */ 1863951c6300SRichard Henderson 1864a686dc71SRichard Henderson tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */ 1865a686dc71SRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */ 18662b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 18672b836c2aSRichard Henderson tcg_gen_sari_i64(t1, t1, 32); /* t1 = ssssdc.. */ 18682b836c2aSRichard Henderson } else { 1869a686dc71SRichard Henderson tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */ 18702b836c2aSRichard Henderson } 18719c406215SPhilippe Mathieu-Daudé tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba (OS) */ 18729c406215SPhilippe Mathieu-Daudé /* ....dcba (else) */ 1873951c6300SRichard Henderson 1874951c6300SRichard Henderson tcg_temp_free_i64(t0); 1875951c6300SRichard Henderson tcg_temp_free_i64(t1); 1876951c6300SRichard Henderson } 1877951c6300SRichard Henderson } 1878951c6300SRichard Henderson 187995180e75SPhilippe Mathieu-Daudé /* 188095180e75SPhilippe Mathieu-Daudé * bswap64_i64: 64-bit byte swap on a 64-bit value. 188195180e75SPhilippe Mathieu-Daudé * 188295180e75SPhilippe Mathieu-Daudé * Byte pattern: abcdefgh -> hgfedcba 188395180e75SPhilippe Mathieu-Daudé */ 1884951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg) 1885951c6300SRichard Henderson { 18863a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1887951c6300SRichard Henderson TCGv_i32 t0, t1; 18885dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 18895dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 1890951c6300SRichard Henderson 1891951c6300SRichard Henderson tcg_gen_bswap32_i32(t0, TCGV_LOW(arg)); 1892951c6300SRichard Henderson tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg)); 1893951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), t1); 1894951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t0); 1895951c6300SRichard Henderson tcg_temp_free_i32(t0); 1896951c6300SRichard Henderson tcg_temp_free_i32(t1); 18973a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap64_i64) { 1898587195bdSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0); 1899951c6300SRichard Henderson } else { 19005dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 19015dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 19025dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 1903951c6300SRichard Henderson 19049e821eabSRichard Henderson /* arg = abcdefgh */ 19059e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull); 19069e821eabSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .abcdefg */ 19079e821eabSRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .b.d.f.h */ 19089e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .a.c.e.g */ 19099e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = b.d.f.h. */ 19109e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = badcfehg */ 1911951c6300SRichard Henderson 19129e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull); 19139e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ..badcfe */ 19149e821eabSRichard Henderson tcg_gen_and_i64(t1, ret, t2); /* t1 = ..dc..hg */ 19159e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = ..ba..fe */ 19169e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 16); /* t1 = dc..hg.. */ 19179e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = dcbahgfe */ 1918951c6300SRichard Henderson 19199e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 32); /* t0 = ....dcba */ 19209e821eabSRichard Henderson tcg_gen_shli_i64(t1, ret, 32); /* t1 = hgfe.... */ 19219e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = hgfedcba */ 1922951c6300SRichard Henderson 1923951c6300SRichard Henderson tcg_temp_free_i64(t0); 1924951c6300SRichard Henderson tcg_temp_free_i64(t1); 19259e821eabSRichard Henderson tcg_temp_free_i64(t2); 1926951c6300SRichard Henderson } 1927951c6300SRichard Henderson } 1928951c6300SRichard Henderson 1929b8976aa5SPhilippe Mathieu-Daudé /* 1930b8976aa5SPhilippe Mathieu-Daudé * hswap_i64: Swap 16-bit halfwords within a 64-bit value. 1931b8976aa5SPhilippe Mathieu-Daudé * See also include/qemu/bitops.h, hswap64. 1932b8976aa5SPhilippe Mathieu-Daudé * 1933b8976aa5SPhilippe Mathieu-Daudé * Byte pattern: abcdefgh -> ghefcdab 1934b8976aa5SPhilippe Mathieu-Daudé */ 193546be8425SRichard Henderson void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg) 193646be8425SRichard Henderson { 193746be8425SRichard Henderson uint64_t m = 0x0000ffff0000ffffull; 19385dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 19395dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 194046be8425SRichard Henderson 1941b8976aa5SPhilippe Mathieu-Daudé /* arg = abcdefgh */ 1942b8976aa5SPhilippe Mathieu-Daudé tcg_gen_rotli_i64(t1, arg, 32); /* t1 = efghabcd */ 1943b8976aa5SPhilippe Mathieu-Daudé tcg_gen_andi_i64(t0, t1, m); /* t0 = ..gh..cd */ 1944b8976aa5SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t0, t0, 16); /* t0 = gh..cd.. */ 1945b8976aa5SPhilippe Mathieu-Daudé tcg_gen_shri_i64(t1, t1, 16); /* t1 = ..efghab */ 1946b8976aa5SPhilippe Mathieu-Daudé tcg_gen_andi_i64(t1, t1, m); /* t1 = ..ef..ab */ 1947b8976aa5SPhilippe Mathieu-Daudé tcg_gen_or_i64(ret, t0, t1); /* ret = ghefcdab */ 194846be8425SRichard Henderson 194946be8425SRichard Henderson tcg_temp_free_i64(t0); 195046be8425SRichard Henderson tcg_temp_free_i64(t1); 195146be8425SRichard Henderson } 195246be8425SRichard Henderson 1953ad262fb5SPhilippe Mathieu-Daudé /* 1954ad262fb5SPhilippe Mathieu-Daudé * wswap_i64: Swap 32-bit words within a 64-bit value. 1955ad262fb5SPhilippe Mathieu-Daudé * 1956ad262fb5SPhilippe Mathieu-Daudé * Byte pattern: abcdefgh -> efghabcd 1957ad262fb5SPhilippe Mathieu-Daudé */ 195846be8425SRichard Henderson void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg) 195946be8425SRichard Henderson { 196046be8425SRichard Henderson /* Swapping 2 32-bit elements is a rotate. */ 196146be8425SRichard Henderson tcg_gen_rotli_i64(ret, arg, 32); 196246be8425SRichard Henderson } 196346be8425SRichard Henderson 1964951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg) 1965951c6300SRichard Henderson { 19663a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19673a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 19683a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 19693a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_not_i64) { 1970951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg); 1971951c6300SRichard Henderson } else { 1972951c6300SRichard Henderson tcg_gen_xori_i64(ret, arg, -1); 1973951c6300SRichard Henderson } 1974951c6300SRichard Henderson } 1975951c6300SRichard Henderson 1976951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1977951c6300SRichard Henderson { 19783a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19793a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 19803a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 19813a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_andc_i64) { 1982951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2); 1983951c6300SRichard Henderson } else { 19845dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 1985951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 1986951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, t0); 1987951c6300SRichard Henderson tcg_temp_free_i64(t0); 1988951c6300SRichard Henderson } 1989951c6300SRichard Henderson } 1990951c6300SRichard Henderson 1991951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1992951c6300SRichard Henderson { 19933a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19943a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 19953a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 19963a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_eqv_i64) { 1997951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2); 1998951c6300SRichard Henderson } else { 1999951c6300SRichard Henderson tcg_gen_xor_i64(ret, arg1, arg2); 2000951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 2001951c6300SRichard Henderson } 2002951c6300SRichard Henderson } 2003951c6300SRichard Henderson 2004951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2005951c6300SRichard Henderson { 20063a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 20073a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 20083a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 20093a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nand_i64) { 2010951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2); 2011951c6300SRichard Henderson } else { 2012951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, arg2); 2013951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 2014951c6300SRichard Henderson } 2015951c6300SRichard Henderson } 2016951c6300SRichard Henderson 2017951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2018951c6300SRichard Henderson { 20193a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 20203a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 20213a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 20223a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nor_i64) { 2023951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2); 2024951c6300SRichard Henderson } else { 2025951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, arg2); 2026951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 2027951c6300SRichard Henderson } 2028951c6300SRichard Henderson } 2029951c6300SRichard Henderson 2030951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2031951c6300SRichard Henderson { 20323a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 20333a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 20343a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 20353a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_orc_i64) { 2036951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2); 2037951c6300SRichard Henderson } else { 20385dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2039951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 2040951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, t0); 2041951c6300SRichard Henderson tcg_temp_free_i64(t0); 2042951c6300SRichard Henderson } 2043951c6300SRichard Henderson } 2044951c6300SRichard Henderson 20450e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 20460e28d006SRichard Henderson { 20470e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i64) { 20480e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2); 20490e28d006SRichard Henderson } else { 20500e28d006SRichard Henderson gen_helper_clz_i64(ret, arg1, arg2); 20510e28d006SRichard Henderson } 20520e28d006SRichard Henderson } 20530e28d006SRichard Henderson 20540e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 20550e28d006SRichard Henderson { 20560e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 20570e28d006SRichard Henderson && TCG_TARGET_HAS_clz_i32 20580e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 20595dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 206011d11d61SRichard Henderson tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32); 20610e28d006SRichard Henderson tcg_gen_addi_i32(t, t, 32); 20620e28d006SRichard Henderson tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t); 20630e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 20640e28d006SRichard Henderson tcg_temp_free_i32(t); 20650e28d006SRichard Henderson } else { 2066f04de891SRichard Henderson tcg_gen_clz_i64(ret, arg1, tcg_constant_i64(arg2)); 20670e28d006SRichard Henderson } 20680e28d006SRichard Henderson } 20690e28d006SRichard Henderson 20700e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 20710e28d006SRichard Henderson { 20720e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i64) { 20730e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2); 207414e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) { 20755dd48602SRichard Henderson TCGv_i64 z, t = tcg_temp_ebb_new_i64(); 207614e99210SRichard Henderson 207714e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 207814e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 207914e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 208014e99210SRichard Henderson tcg_gen_ctpop_i64(t, t); 208114e99210SRichard Henderson } else { 208214e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 64, don't fight it. */ 208314e99210SRichard Henderson tcg_gen_neg_i64(t, arg1); 208414e99210SRichard Henderson tcg_gen_and_i64(t, t, arg1); 208514e99210SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 208614e99210SRichard Henderson tcg_gen_xori_i64(t, t, 63); 208714e99210SRichard Henderson } 208811d11d61SRichard Henderson z = tcg_constant_i64(0); 208914e99210SRichard Henderson tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t); 209014e99210SRichard Henderson tcg_temp_free_i64(t); 209114e99210SRichard Henderson tcg_temp_free_i64(z); 20920e28d006SRichard Henderson } else { 20930e28d006SRichard Henderson gen_helper_ctz_i64(ret, arg1, arg2); 20940e28d006SRichard Henderson } 20950e28d006SRichard Henderson } 20960e28d006SRichard Henderson 20970e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 20980e28d006SRichard Henderson { 20990e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 21000e28d006SRichard Henderson && TCG_TARGET_HAS_ctz_i32 21010e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 21025dd48602SRichard Henderson TCGv_i32 t32 = tcg_temp_ebb_new_i32(); 210311d11d61SRichard Henderson tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32); 21040e28d006SRichard Henderson tcg_gen_addi_i32(t32, t32, 32); 21050e28d006SRichard Henderson tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32); 21060e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 21070e28d006SRichard Henderson tcg_temp_free_i32(t32); 210814e99210SRichard Henderson } else if (!TCG_TARGET_HAS_ctz_i64 210914e99210SRichard Henderson && TCG_TARGET_HAS_ctpop_i64 211014e99210SRichard Henderson && arg2 == 64) { 211114e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 21125dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 211314e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 211414e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 211514e99210SRichard Henderson tcg_gen_ctpop_i64(ret, t); 211614e99210SRichard Henderson tcg_temp_free_i64(t); 21170e28d006SRichard Henderson } else { 2118f04de891SRichard Henderson tcg_gen_ctz_i64(ret, arg1, tcg_constant_i64(arg2)); 21190e28d006SRichard Henderson } 21200e28d006SRichard Henderson } 21210e28d006SRichard Henderson 2122086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg) 2123086920c2SRichard Henderson { 2124086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) { 21255dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2126086920c2SRichard Henderson tcg_gen_sari_i64(t, arg, 63); 2127086920c2SRichard Henderson tcg_gen_xor_i64(t, t, arg); 2128086920c2SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 2129086920c2SRichard Henderson tcg_gen_subi_i64(ret, t, 1); 2130086920c2SRichard Henderson tcg_temp_free_i64(t); 2131086920c2SRichard Henderson } else { 2132086920c2SRichard Henderson gen_helper_clrsb_i64(ret, arg); 2133086920c2SRichard Henderson } 2134086920c2SRichard Henderson } 2135086920c2SRichard Henderson 2136a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1) 2137a768e4e9SRichard Henderson { 2138a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 2139a768e4e9SRichard Henderson tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1); 2140a768e4e9SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) { 2141a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2142a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2143a768e4e9SRichard Henderson tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret)); 2144a768e4e9SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2145a768e4e9SRichard Henderson } else { 2146a768e4e9SRichard Henderson gen_helper_ctpop_i64(ret, arg1); 2147a768e4e9SRichard Henderson } 2148a768e4e9SRichard Henderson } 2149a768e4e9SRichard Henderson 2150951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2151951c6300SRichard Henderson { 2152951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 2153951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2); 2154951c6300SRichard Henderson } else { 2155951c6300SRichard Henderson TCGv_i64 t0, t1; 21565dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 21575dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2158951c6300SRichard Henderson tcg_gen_shl_i64(t0, arg1, arg2); 2159951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 2160951c6300SRichard Henderson tcg_gen_shr_i64(t1, arg1, t1); 2161951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2162951c6300SRichard Henderson tcg_temp_free_i64(t0); 2163951c6300SRichard Henderson tcg_temp_free_i64(t1); 2164951c6300SRichard Henderson } 2165951c6300SRichard Henderson } 2166951c6300SRichard Henderson 216707dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2168951c6300SRichard Henderson { 216907dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2170951c6300SRichard Henderson /* some cases can be optimized here */ 2171951c6300SRichard Henderson if (arg2 == 0) { 2172951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 2173951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i64) { 217411d11d61SRichard Henderson tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2)); 2175951c6300SRichard Henderson } else { 2176951c6300SRichard Henderson TCGv_i64 t0, t1; 21775dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 21785dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2179951c6300SRichard Henderson tcg_gen_shli_i64(t0, arg1, arg2); 2180951c6300SRichard Henderson tcg_gen_shri_i64(t1, arg1, 64 - arg2); 2181951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2182951c6300SRichard Henderson tcg_temp_free_i64(t0); 2183951c6300SRichard Henderson tcg_temp_free_i64(t1); 2184951c6300SRichard Henderson } 2185951c6300SRichard Henderson } 2186951c6300SRichard Henderson 2187951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2188951c6300SRichard Henderson { 2189951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 2190951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2); 2191951c6300SRichard Henderson } else { 2192951c6300SRichard Henderson TCGv_i64 t0, t1; 21935dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 21945dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2195951c6300SRichard Henderson tcg_gen_shr_i64(t0, arg1, arg2); 2196951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 2197951c6300SRichard Henderson tcg_gen_shl_i64(t1, arg1, t1); 2198951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2199951c6300SRichard Henderson tcg_temp_free_i64(t0); 2200951c6300SRichard Henderson tcg_temp_free_i64(t1); 2201951c6300SRichard Henderson } 2202951c6300SRichard Henderson } 2203951c6300SRichard Henderson 220407dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2205951c6300SRichard Henderson { 220607dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2207951c6300SRichard Henderson /* some cases can be optimized here */ 2208951c6300SRichard Henderson if (arg2 == 0) { 2209951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 2210951c6300SRichard Henderson } else { 2211951c6300SRichard Henderson tcg_gen_rotli_i64(ret, arg1, 64 - arg2); 2212951c6300SRichard Henderson } 2213951c6300SRichard Henderson } 2214951c6300SRichard Henderson 2215951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, 2216951c6300SRichard Henderson unsigned int ofs, unsigned int len) 2217951c6300SRichard Henderson { 2218951c6300SRichard Henderson uint64_t mask; 2219951c6300SRichard Henderson TCGv_i64 t1; 2220951c6300SRichard Henderson 2221951c6300SRichard Henderson tcg_debug_assert(ofs < 64); 22220d0d309dSRichard Henderson tcg_debug_assert(len > 0); 2223951c6300SRichard Henderson tcg_debug_assert(len <= 64); 2224951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 64); 2225951c6300SRichard Henderson 22260d0d309dSRichard Henderson if (len == 64) { 2227951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg2); 2228951c6300SRichard Henderson return; 2229951c6300SRichard Henderson } 2230951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) { 2231951c6300SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); 2232951c6300SRichard Henderson return; 2233951c6300SRichard Henderson } 2234951c6300SRichard Henderson 22353a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2236951c6300SRichard Henderson if (ofs >= 32) { 2237951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 2238951c6300SRichard Henderson TCGV_LOW(arg2), ofs - 32, len); 2239951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2240951c6300SRichard Henderson return; 2241951c6300SRichard Henderson } 2242951c6300SRichard Henderson if (ofs + len <= 32) { 2243951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1), 2244951c6300SRichard Henderson TCGV_LOW(arg2), ofs, len); 2245951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2246951c6300SRichard Henderson return; 2247951c6300SRichard Henderson } 22483a13c3f3SRichard Henderson } 2249951c6300SRichard Henderson 22505dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2251951c6300SRichard Henderson 2252b0a60567SRichard Henderson if (TCG_TARGET_HAS_extract2_i64) { 2253b0a60567SRichard Henderson if (ofs + len == 64) { 2254b0a60567SRichard Henderson tcg_gen_shli_i64(t1, arg1, len); 2255b0a60567SRichard Henderson tcg_gen_extract2_i64(ret, t1, arg2, len); 2256b0a60567SRichard Henderson goto done; 2257b0a60567SRichard Henderson } 2258b0a60567SRichard Henderson if (ofs == 0) { 2259b0a60567SRichard Henderson tcg_gen_extract2_i64(ret, arg1, arg2, len); 2260b0a60567SRichard Henderson tcg_gen_rotli_i64(ret, ret, len); 2261b0a60567SRichard Henderson goto done; 2262b0a60567SRichard Henderson } 2263b0a60567SRichard Henderson } 2264b0a60567SRichard Henderson 2265b0a60567SRichard Henderson mask = (1ull << len) - 1; 2266951c6300SRichard Henderson if (ofs + len < 64) { 2267951c6300SRichard Henderson tcg_gen_andi_i64(t1, arg2, mask); 2268951c6300SRichard Henderson tcg_gen_shli_i64(t1, t1, ofs); 2269951c6300SRichard Henderson } else { 2270951c6300SRichard Henderson tcg_gen_shli_i64(t1, arg2, ofs); 2271951c6300SRichard Henderson } 2272951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg1, ~(mask << ofs)); 2273951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2274b0a60567SRichard Henderson done: 2275951c6300SRichard Henderson tcg_temp_free_i64(t1); 2276951c6300SRichard Henderson } 2277951c6300SRichard Henderson 227807cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, 227907cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 228007cc68d5SRichard Henderson { 228107cc68d5SRichard Henderson tcg_debug_assert(ofs < 64); 228207cc68d5SRichard Henderson tcg_debug_assert(len > 0); 228307cc68d5SRichard Henderson tcg_debug_assert(len <= 64); 228407cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 64); 228507cc68d5SRichard Henderson 228607cc68d5SRichard Henderson if (ofs + len == 64) { 228707cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 228807cc68d5SRichard Henderson } else if (ofs == 0) { 228907cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 229007cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i64 229107cc68d5SRichard Henderson && TCG_TARGET_deposit_i64_valid(ofs, len)) { 229211d11d61SRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 229307cc68d5SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); 229407cc68d5SRichard Henderson } else { 229507cc68d5SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 229607cc68d5SRichard Henderson if (ofs >= 32) { 229707cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg), 229807cc68d5SRichard Henderson ofs - 32, len); 229907cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 230007cc68d5SRichard Henderson return; 230107cc68d5SRichard Henderson } 230207cc68d5SRichard Henderson if (ofs + len <= 32) { 230307cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 230407cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 230507cc68d5SRichard Henderson return; 230607cc68d5SRichard Henderson } 230707cc68d5SRichard Henderson } 230807cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 230907cc68d5SRichard Henderson which allows ARG to stay live. */ 231007cc68d5SRichard Henderson switch (len) { 231107cc68d5SRichard Henderson case 32: 231207cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 231307cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 231407cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 231507cc68d5SRichard Henderson return; 231607cc68d5SRichard Henderson } 231707cc68d5SRichard Henderson break; 231807cc68d5SRichard Henderson case 16: 231907cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 232007cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 232107cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 232207cc68d5SRichard Henderson return; 232307cc68d5SRichard Henderson } 232407cc68d5SRichard Henderson break; 232507cc68d5SRichard Henderson case 8: 232607cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 232707cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 232807cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 232907cc68d5SRichard Henderson return; 233007cc68d5SRichard Henderson } 233107cc68d5SRichard Henderson break; 233207cc68d5SRichard Henderson } 233307cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 233407cc68d5SRichard Henderson switch (ofs + len) { 233507cc68d5SRichard Henderson case 32: 233607cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 233707cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 233807cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, ret); 233907cc68d5SRichard Henderson return; 234007cc68d5SRichard Henderson } 234107cc68d5SRichard Henderson break; 234207cc68d5SRichard Henderson case 16: 234307cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 234407cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 234507cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, ret); 234607cc68d5SRichard Henderson return; 234707cc68d5SRichard Henderson } 234807cc68d5SRichard Henderson break; 234907cc68d5SRichard Henderson case 8: 235007cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 235107cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 235207cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, ret); 235307cc68d5SRichard Henderson return; 235407cc68d5SRichard Henderson } 235507cc68d5SRichard Henderson break; 235607cc68d5SRichard Henderson } 235707cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 235807cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 235907cc68d5SRichard Henderson } 236007cc68d5SRichard Henderson } 236107cc68d5SRichard Henderson 23627ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, 23637ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 23647ec8bab3SRichard Henderson { 23657ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 23667ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 23677ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 23687ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 23697ec8bab3SRichard Henderson 23707ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 23717ec8bab3SRichard Henderson if (ofs + len == 64) { 23727ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, 64 - len); 23737ec8bab3SRichard Henderson return; 23747ec8bab3SRichard Henderson } 23757ec8bab3SRichard Henderson if (ofs == 0) { 23767ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 23777ec8bab3SRichard Henderson return; 23787ec8bab3SRichard Henderson } 23797ec8bab3SRichard Henderson 23807ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 23817ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 23827ec8bab3SRichard Henderson if (ofs >= 32) { 23837ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 23847ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 23857ec8bab3SRichard Henderson return; 23867ec8bab3SRichard Henderson } 23877ec8bab3SRichard Henderson if (ofs + len <= 32) { 23887ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 23897ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 23907ec8bab3SRichard Henderson return; 23917ec8bab3SRichard Henderson } 23927ec8bab3SRichard Henderson /* The field is split across two words. One double-word 23937ec8bab3SRichard Henderson shift is better than two double-word shifts. */ 23947ec8bab3SRichard Henderson goto do_shift_and; 23957ec8bab3SRichard Henderson } 23967ec8bab3SRichard Henderson 23977ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i64 23987ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 23997ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len); 24007ec8bab3SRichard Henderson return; 24017ec8bab3SRichard Henderson } 24027ec8bab3SRichard Henderson 24037ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 24047ec8bab3SRichard Henderson switch (ofs + len) { 24057ec8bab3SRichard Henderson case 32: 24067ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 24077ec8bab3SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 24087ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 24097ec8bab3SRichard Henderson return; 24107ec8bab3SRichard Henderson } 24117ec8bab3SRichard Henderson break; 24127ec8bab3SRichard Henderson case 16: 24137ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 24147ec8bab3SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 24157ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 24167ec8bab3SRichard Henderson return; 24177ec8bab3SRichard Henderson } 24187ec8bab3SRichard Henderson break; 24197ec8bab3SRichard Henderson case 8: 24207ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 24217ec8bab3SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 24227ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 24237ec8bab3SRichard Henderson return; 24247ec8bab3SRichard Henderson } 24257ec8bab3SRichard Henderson break; 24267ec8bab3SRichard Henderson } 24277ec8bab3SRichard Henderson 24287ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 24297ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special cases of 16 and 32, 24307ec8bab3SRichard Henderson so that we get ext8u, ext16u, and ext32u. */ 24317ec8bab3SRichard Henderson switch (len) { 24327ec8bab3SRichard Henderson case 1 ... 8: case 16: case 32: 24337ec8bab3SRichard Henderson do_shift_and: 24347ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 24357ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, ret, (1ull << len) - 1); 24367ec8bab3SRichard Henderson break; 24377ec8bab3SRichard Henderson default: 24387ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 24397ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, 64 - len); 24407ec8bab3SRichard Henderson break; 24417ec8bab3SRichard Henderson } 24427ec8bab3SRichard Henderson } 24437ec8bab3SRichard Henderson 24447ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg, 24457ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 24467ec8bab3SRichard Henderson { 24477ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 24487ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 24497ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 24507ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 24517ec8bab3SRichard Henderson 24527ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if sextract is supported. */ 24537ec8bab3SRichard Henderson if (ofs + len == 64) { 24547ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, arg, 64 - len); 24557ec8bab3SRichard Henderson return; 24567ec8bab3SRichard Henderson } 24577ec8bab3SRichard Henderson if (ofs == 0) { 24587ec8bab3SRichard Henderson switch (len) { 24597ec8bab3SRichard Henderson case 32: 24607ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 24617ec8bab3SRichard Henderson return; 24627ec8bab3SRichard Henderson case 16: 24637ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 24647ec8bab3SRichard Henderson return; 24657ec8bab3SRichard Henderson case 8: 24667ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 24677ec8bab3SRichard Henderson return; 24687ec8bab3SRichard Henderson } 24697ec8bab3SRichard Henderson } 24707ec8bab3SRichard Henderson 24717ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 24727ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 24737ec8bab3SRichard Henderson if (ofs >= 32) { 24747ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 24757ec8bab3SRichard Henderson } else if (ofs + len <= 32) { 24767ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 24777ec8bab3SRichard Henderson } else if (ofs == 0) { 24787ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 24797ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32); 24807ec8bab3SRichard Henderson return; 24817ec8bab3SRichard Henderson } else if (len > 32) { 24825dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 24837ec8bab3SRichard Henderson /* Extract the bits for the high word normally. */ 24847ec8bab3SRichard Henderson tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32); 24857ec8bab3SRichard Henderson /* Shift the field down for the low part. */ 24867ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 24877ec8bab3SRichard Henderson /* Overwrite the shift into the high part. */ 24887ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t); 24897ec8bab3SRichard Henderson tcg_temp_free_i32(t); 24907ec8bab3SRichard Henderson return; 24917ec8bab3SRichard Henderson } else { 24927ec8bab3SRichard Henderson /* Shift the field down for the low part, such that the 24937ec8bab3SRichard Henderson field sits at the MSB. */ 24947ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs + len - 32); 24957ec8bab3SRichard Henderson /* Shift the field down from the MSB, sign extending. */ 24967ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len); 24977ec8bab3SRichard Henderson } 24987ec8bab3SRichard Henderson /* Sign-extend the field from 32 bits. */ 24997ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 25007ec8bab3SRichard Henderson return; 25017ec8bab3SRichard Henderson } 25027ec8bab3SRichard Henderson 25037ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i64 25047ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 25057ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); 25067ec8bab3SRichard Henderson return; 25077ec8bab3SRichard Henderson } 25087ec8bab3SRichard Henderson 25097ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 25107ec8bab3SRichard Henderson switch (ofs + len) { 25117ec8bab3SRichard Henderson case 32: 25127ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 25137ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 25147ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 25157ec8bab3SRichard Henderson return; 25167ec8bab3SRichard Henderson } 25177ec8bab3SRichard Henderson break; 25187ec8bab3SRichard Henderson case 16: 25197ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 25207ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 25217ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 25227ec8bab3SRichard Henderson return; 25237ec8bab3SRichard Henderson } 25247ec8bab3SRichard Henderson break; 25257ec8bab3SRichard Henderson case 8: 25267ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 25277ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 25287ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 25297ec8bab3SRichard Henderson return; 25307ec8bab3SRichard Henderson } 25317ec8bab3SRichard Henderson break; 25327ec8bab3SRichard Henderson } 25337ec8bab3SRichard Henderson switch (len) { 25347ec8bab3SRichard Henderson case 32: 25357ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 25367ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 25377ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, ret); 25387ec8bab3SRichard Henderson return; 25397ec8bab3SRichard Henderson } 25407ec8bab3SRichard Henderson break; 25417ec8bab3SRichard Henderson case 16: 25427ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 25437ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 25447ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, ret); 25457ec8bab3SRichard Henderson return; 25467ec8bab3SRichard Henderson } 25477ec8bab3SRichard Henderson break; 25487ec8bab3SRichard Henderson case 8: 25497ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 25507ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 25517ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, ret); 25527ec8bab3SRichard Henderson return; 25537ec8bab3SRichard Henderson } 25547ec8bab3SRichard Henderson break; 25557ec8bab3SRichard Henderson } 25567ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 25577ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, 64 - len); 25587ec8bab3SRichard Henderson } 25597ec8bab3SRichard Henderson 25602089fcc9SDavid Hildenbrand /* 25612089fcc9SDavid Hildenbrand * Extract 64 bits from a 128-bit input, ah:al, starting from ofs. 25622089fcc9SDavid Hildenbrand * Unlike tcg_gen_extract_i64 above, len is fixed at 64. 25632089fcc9SDavid Hildenbrand */ 25642089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah, 25652089fcc9SDavid Hildenbrand unsigned int ofs) 25662089fcc9SDavid Hildenbrand { 25672089fcc9SDavid Hildenbrand tcg_debug_assert(ofs <= 64); 25682089fcc9SDavid Hildenbrand if (ofs == 0) { 25692089fcc9SDavid Hildenbrand tcg_gen_mov_i64(ret, al); 25702089fcc9SDavid Hildenbrand } else if (ofs == 64) { 25712089fcc9SDavid Hildenbrand tcg_gen_mov_i64(ret, ah); 25722089fcc9SDavid Hildenbrand } else if (al == ah) { 25732089fcc9SDavid Hildenbrand tcg_gen_rotri_i64(ret, al, ofs); 2574fce1296fSRichard Henderson } else if (TCG_TARGET_HAS_extract2_i64) { 2575fce1296fSRichard Henderson tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs); 25762089fcc9SDavid Hildenbrand } else { 25775dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 25782089fcc9SDavid Hildenbrand tcg_gen_shri_i64(t0, al, ofs); 25792089fcc9SDavid Hildenbrand tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs); 25802089fcc9SDavid Hildenbrand tcg_temp_free_i64(t0); 25812089fcc9SDavid Hildenbrand } 25822089fcc9SDavid Hildenbrand } 25832089fcc9SDavid Hildenbrand 2584951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, 2585951c6300SRichard Henderson TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2) 2586951c6300SRichard Henderson { 258737ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 258837ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v1); 258937ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 259037ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v2); 259137ed3bf1SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 25925dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 25935dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 2594951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, 2595951c6300SRichard Henderson TCGV_LOW(c1), TCGV_HIGH(c1), 2596951c6300SRichard Henderson TCGV_LOW(c2), TCGV_HIGH(c2), cond); 2597951c6300SRichard Henderson 2598951c6300SRichard Henderson if (TCG_TARGET_HAS_movcond_i32) { 2599951c6300SRichard Henderson tcg_gen_movi_i32(t1, 0); 2600951c6300SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1, 2601951c6300SRichard Henderson TCGV_LOW(v1), TCGV_LOW(v2)); 2602951c6300SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1, 2603951c6300SRichard Henderson TCGV_HIGH(v1), TCGV_HIGH(v2)); 2604951c6300SRichard Henderson } else { 2605951c6300SRichard Henderson tcg_gen_neg_i32(t0, t0); 2606951c6300SRichard Henderson 2607951c6300SRichard Henderson tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); 2608951c6300SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); 2609951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); 2610951c6300SRichard Henderson 2611951c6300SRichard Henderson tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); 2612951c6300SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); 2613951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); 2614951c6300SRichard Henderson } 2615951c6300SRichard Henderson tcg_temp_free_i32(t0); 2616951c6300SRichard Henderson tcg_temp_free_i32(t1); 26173a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_movcond_i64) { 2618951c6300SRichard Henderson tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); 2619951c6300SRichard Henderson } else { 26205dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 26215dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 26224a883870SRichard Henderson tcg_gen_negsetcond_i64(cond, t0, c1, c2); 2623951c6300SRichard Henderson tcg_gen_and_i64(t1, v1, t0); 2624951c6300SRichard Henderson tcg_gen_andc_i64(ret, v2, t0); 2625951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2626951c6300SRichard Henderson tcg_temp_free_i64(t0); 2627951c6300SRichard Henderson tcg_temp_free_i64(t1); 2628951c6300SRichard Henderson } 2629951c6300SRichard Henderson } 2630951c6300SRichard Henderson 2631951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2632951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2633951c6300SRichard Henderson { 2634951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i64) { 2635951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh); 2636951c6300SRichard Henderson } else { 26375dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 26385dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 2639951c6300SRichard Henderson tcg_gen_add_i64(t0, al, bl); 2640951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al); 2641951c6300SRichard Henderson tcg_gen_add_i64(rh, ah, bh); 2642951c6300SRichard Henderson tcg_gen_add_i64(rh, rh, t1); 2643951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2644951c6300SRichard Henderson tcg_temp_free_i64(t0); 2645951c6300SRichard Henderson tcg_temp_free_i64(t1); 2646951c6300SRichard Henderson } 2647951c6300SRichard Henderson } 2648951c6300SRichard Henderson 2649951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2650951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2651951c6300SRichard Henderson { 2652951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i64) { 2653951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh); 2654951c6300SRichard Henderson } else { 26555dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 26565dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 2657951c6300SRichard Henderson tcg_gen_sub_i64(t0, al, bl); 2658951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl); 2659951c6300SRichard Henderson tcg_gen_sub_i64(rh, ah, bh); 2660951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t1); 2661951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2662951c6300SRichard Henderson tcg_temp_free_i64(t0); 2663951c6300SRichard Henderson tcg_temp_free_i64(t1); 2664951c6300SRichard Henderson } 2665951c6300SRichard Henderson } 2666951c6300SRichard Henderson 2667951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2668951c6300SRichard Henderson { 2669951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i64) { 2670951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); 2671951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i64) { 26725dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2673951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2674951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2); 2675951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 2676951c6300SRichard Henderson tcg_temp_free_i64(t); 2677951c6300SRichard Henderson } else { 26785dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2679951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 2680951c6300SRichard Henderson gen_helper_muluh_i64(rh, arg1, arg2); 2681951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2682951c6300SRichard Henderson tcg_temp_free_i64(t0); 2683951c6300SRichard Henderson } 2684951c6300SRichard Henderson } 2685951c6300SRichard Henderson 2686951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2687951c6300SRichard Henderson { 2688951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i64) { 2689951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); 2690951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i64) { 26915dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2692951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2693951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2); 2694951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 2695951c6300SRichard Henderson tcg_temp_free_i64(t); 2696951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) { 26975dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 26985dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 26995dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 27005dd48602SRichard Henderson TCGv_i64 t3 = tcg_temp_ebb_new_i64(); 2701951c6300SRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 2702951c6300SRichard Henderson /* Adjust for negative inputs. */ 2703951c6300SRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 2704951c6300SRichard Henderson tcg_gen_sari_i64(t3, arg2, 63); 2705951c6300SRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 2706951c6300SRichard Henderson tcg_gen_and_i64(t3, t3, arg1); 2707951c6300SRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 2708951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t3); 2709951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2710951c6300SRichard Henderson tcg_temp_free_i64(t0); 2711951c6300SRichard Henderson tcg_temp_free_i64(t1); 2712951c6300SRichard Henderson tcg_temp_free_i64(t2); 2713951c6300SRichard Henderson tcg_temp_free_i64(t3); 2714951c6300SRichard Henderson } else { 27155dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2716951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 2717951c6300SRichard Henderson gen_helper_mulsh_i64(rh, arg1, arg2); 2718951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2719951c6300SRichard Henderson tcg_temp_free_i64(t0); 2720951c6300SRichard Henderson } 2721951c6300SRichard Henderson } 2722951c6300SRichard Henderson 27235087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 27245087abfbSRichard Henderson { 27255dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 27265dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 27275dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 27285087abfbSRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 27295087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 27305087abfbSRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 27315087abfbSRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 27325087abfbSRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 27335087abfbSRichard Henderson tcg_gen_mov_i64(rl, t0); 27345087abfbSRichard Henderson tcg_temp_free_i64(t0); 27355087abfbSRichard Henderson tcg_temp_free_i64(t1); 27365087abfbSRichard Henderson tcg_temp_free_i64(t2); 27375087abfbSRichard Henderson } 27385087abfbSRichard Henderson 2739b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2740b87fb8cdSRichard Henderson { 2741b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); 2742b87fb8cdSRichard Henderson } 2743b87fb8cdSRichard Henderson 2744b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2745b87fb8cdSRichard Henderson { 2746b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); 2747b87fb8cdSRichard Henderson } 2748b87fb8cdSRichard Henderson 2749b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2750b87fb8cdSRichard Henderson { 2751b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); 2752b87fb8cdSRichard Henderson } 2753b87fb8cdSRichard Henderson 2754b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2755b87fb8cdSRichard Henderson { 2756b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); 2757b87fb8cdSRichard Henderson } 2758b87fb8cdSRichard Henderson 2759ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a) 2760ff1f11f7SRichard Henderson { 27615dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2762ff1f11f7SRichard Henderson 2763ff1f11f7SRichard Henderson tcg_gen_sari_i64(t, a, 63); 2764ff1f11f7SRichard Henderson tcg_gen_xor_i64(ret, a, t); 2765ff1f11f7SRichard Henderson tcg_gen_sub_i64(ret, ret, t); 2766ff1f11f7SRichard Henderson tcg_temp_free_i64(t); 2767ff1f11f7SRichard Henderson } 2768ff1f11f7SRichard Henderson 2769951c6300SRichard Henderson /* Size changing operations. */ 2770951c6300SRichard Henderson 2771609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2772951c6300SRichard Henderson { 27733a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2774951c6300SRichard Henderson tcg_gen_mov_i32(ret, TCGV_LOW(arg)); 277513d885b0SRichard Henderson } else if (TCG_TARGET_HAS_extr_i64_i32) { 2776b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrl_i64_i32, 2777ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2778951c6300SRichard Henderson } else { 2779dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)arg); 2780609ad705SRichard Henderson } 2781609ad705SRichard Henderson } 2782609ad705SRichard Henderson 2783609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2784609ad705SRichard Henderson { 2785609ad705SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2786609ad705SRichard Henderson tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); 278713d885b0SRichard Henderson } else if (TCG_TARGET_HAS_extr_i64_i32) { 2788b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrh_i64_i32, 2789ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2790951c6300SRichard Henderson } else { 27915dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2792609ad705SRichard Henderson tcg_gen_shri_i64(t, arg, 32); 2793dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)t); 2794951c6300SRichard Henderson tcg_temp_free_i64(t); 2795951c6300SRichard Henderson } 2796951c6300SRichard Henderson } 2797951c6300SRichard Henderson 2798951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2799951c6300SRichard Henderson { 28003a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2801951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2802951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 28033a13c3f3SRichard Henderson } else { 2804b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extu_i32_i64, 2805ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 28063a13c3f3SRichard Henderson } 2807951c6300SRichard Henderson } 2808951c6300SRichard Henderson 2809951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2810951c6300SRichard Henderson { 28113a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2812951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2813951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 28143a13c3f3SRichard Henderson } else { 2815b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_ext_i32_i64, 2816ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 28173a13c3f3SRichard Henderson } 2818951c6300SRichard Henderson } 2819951c6300SRichard Henderson 2820951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) 2821951c6300SRichard Henderson { 28223a13c3f3SRichard Henderson TCGv_i64 tmp; 28233a13c3f3SRichard Henderson 28243a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2825951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(dest), low); 2826951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(dest), high); 28273a13c3f3SRichard Henderson return; 28283a13c3f3SRichard Henderson } 28293a13c3f3SRichard Henderson 28305dd48602SRichard Henderson tmp = tcg_temp_ebb_new_i64(); 2831951c6300SRichard Henderson /* These extensions are only needed for type correctness. 2832951c6300SRichard Henderson We may be able to do better given target specific information. */ 2833951c6300SRichard Henderson tcg_gen_extu_i32_i64(tmp, high); 2834951c6300SRichard Henderson tcg_gen_extu_i32_i64(dest, low); 2835951c6300SRichard Henderson /* If deposit is available, use it. Otherwise use the extra 2836951c6300SRichard Henderson knowledge that we have of the zero-extensions above. */ 2837951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { 2838951c6300SRichard Henderson tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); 2839951c6300SRichard Henderson } else { 2840951c6300SRichard Henderson tcg_gen_shli_i64(tmp, tmp, 32); 2841951c6300SRichard Henderson tcg_gen_or_i64(dest, dest, tmp); 2842951c6300SRichard Henderson } 2843951c6300SRichard Henderson tcg_temp_free_i64(tmp); 2844951c6300SRichard Henderson } 2845951c6300SRichard Henderson 2846951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg) 2847951c6300SRichard Henderson { 28483a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2849951c6300SRichard Henderson tcg_gen_mov_i32(lo, TCGV_LOW(arg)); 2850951c6300SRichard Henderson tcg_gen_mov_i32(hi, TCGV_HIGH(arg)); 28513a13c3f3SRichard Henderson } else { 2852609ad705SRichard Henderson tcg_gen_extrl_i64_i32(lo, arg); 2853609ad705SRichard Henderson tcg_gen_extrh_i64_i32(hi, arg); 28543a13c3f3SRichard Henderson } 2855951c6300SRichard Henderson } 2856951c6300SRichard Henderson 2857951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) 2858951c6300SRichard Henderson { 2859951c6300SRichard Henderson tcg_gen_ext32u_i64(lo, arg); 2860951c6300SRichard Henderson tcg_gen_shri_i64(hi, arg, 32); 2861951c6300SRichard Henderson } 2862951c6300SRichard Henderson 28634771e71cSRichard Henderson void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg) 28644771e71cSRichard Henderson { 28654771e71cSRichard Henderson tcg_gen_mov_i64(lo, TCGV128_LOW(arg)); 28664771e71cSRichard Henderson tcg_gen_mov_i64(hi, TCGV128_HIGH(arg)); 28674771e71cSRichard Henderson } 28684771e71cSRichard Henderson 28694771e71cSRichard Henderson void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi) 28704771e71cSRichard Henderson { 28714771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_LOW(ret), lo); 28724771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_HIGH(ret), hi); 28734771e71cSRichard Henderson } 28744771e71cSRichard Henderson 28754771e71cSRichard Henderson void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src) 28764771e71cSRichard Henderson { 28774771e71cSRichard Henderson if (dst != src) { 28784771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src)); 28794771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src)); 28804771e71cSRichard Henderson } 28814771e71cSRichard Henderson } 28824771e71cSRichard Henderson 2883*a01d9792SRichard Henderson void tcg_gen_ld_i128(TCGv_i128 ret, TCGv_ptr base, tcg_target_long offset) 2884*a01d9792SRichard Henderson { 2885*a01d9792SRichard Henderson if (HOST_BIG_ENDIAN) { 2886*a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_HIGH(ret), base, offset); 2887*a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_LOW(ret), base, offset + 8); 2888*a01d9792SRichard Henderson } else { 2889*a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_LOW(ret), base, offset); 2890*a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_HIGH(ret), base, offset + 8); 2891*a01d9792SRichard Henderson } 2892*a01d9792SRichard Henderson } 2893*a01d9792SRichard Henderson 2894*a01d9792SRichard Henderson void tcg_gen_st_i128(TCGv_i128 val, TCGv_ptr base, tcg_target_long offset) 2895*a01d9792SRichard Henderson { 2896*a01d9792SRichard Henderson if (HOST_BIG_ENDIAN) { 2897*a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_HIGH(val), base, offset); 2898*a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_LOW(val), base, offset + 8); 2899*a01d9792SRichard Henderson } else { 2900*a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_LOW(val), base, offset); 2901*a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_HIGH(val), base, offset + 8); 2902*a01d9792SRichard Henderson } 2903*a01d9792SRichard Henderson } 2904*a01d9792SRichard Henderson 2905951c6300SRichard Henderson /* QEMU specific operations. */ 2906951c6300SRichard Henderson 2907d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx) 290807ea28b4SRichard Henderson { 2909eba40358SRichard Henderson /* 2910eba40358SRichard Henderson * Let the jit code return the read-only version of the 2911eba40358SRichard Henderson * TranslationBlock, so that we minimize the pc-relative 2912eba40358SRichard Henderson * distance of the address of the exit_tb code to TB. 2913eba40358SRichard Henderson * This will improve utilization of pc-relative address loads. 2914eba40358SRichard Henderson * 2915eba40358SRichard Henderson * TODO: Move this to translator_loop, so that all const 2916eba40358SRichard Henderson * TranslationBlock pointers refer to read-only memory. 2917eba40358SRichard Henderson * This requires coordination with targets that do not use 2918eba40358SRichard Henderson * the translator_loop. 2919eba40358SRichard Henderson */ 2920eba40358SRichard Henderson uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx; 292107ea28b4SRichard Henderson 292207ea28b4SRichard Henderson if (tb == NULL) { 292307ea28b4SRichard Henderson tcg_debug_assert(idx == 0); 292407ea28b4SRichard Henderson } else if (idx <= TB_EXIT_IDXMAX) { 292507ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG 292607ea28b4SRichard Henderson /* This is an exit following a goto_tb. Verify that we have 292707ea28b4SRichard Henderson seen this numbered exit before, via tcg_gen_goto_tb. */ 292807ea28b4SRichard Henderson tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); 292907ea28b4SRichard Henderson #endif 293007ea28b4SRichard Henderson } else { 293107ea28b4SRichard Henderson /* This is an exit via the exitreq label. */ 293207ea28b4SRichard Henderson tcg_debug_assert(idx == TB_EXIT_REQUESTED); 293307ea28b4SRichard Henderson } 293407ea28b4SRichard Henderson 293507ea28b4SRichard Henderson tcg_gen_op1i(INDEX_op_exit_tb, val); 293607ea28b4SRichard Henderson } 293707ea28b4SRichard Henderson 2938951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx) 2939951c6300SRichard Henderson { 294084f15616SRichard Henderson /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */ 2941b7e4afbdSRichard Henderson tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB)); 2942951c6300SRichard Henderson /* We only support two chained exits. */ 294307ea28b4SRichard Henderson tcg_debug_assert(idx <= TB_EXIT_IDXMAX); 2944951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG 2945a4761232SPhilippe Mathieu-Daudé /* Verify that we haven't seen this numbered exit before. */ 2946b1311c4aSEmilio G. Cota tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0); 2947b1311c4aSEmilio G. Cota tcg_ctx->goto_tb_issue_mask |= 1 << idx; 2948951c6300SRichard Henderson #endif 2949e6d86bedSEmilio G. Cota plugin_gen_disable_mem_helpers(); 2950951c6300SRichard Henderson tcg_gen_op1i(INDEX_op_goto_tb, idx); 2951951c6300SRichard Henderson } 2952951c6300SRichard Henderson 29537f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void) 2954cedbcb01SEmilio G. Cota { 2955e6d86bedSEmilio G. Cota TCGv_ptr ptr; 2956e6d86bedSEmilio G. Cota 2957b7e4afbdSRichard Henderson if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) { 295884f15616SRichard Henderson tcg_gen_exit_tb(NULL, 0); 295984f15616SRichard Henderson return; 296084f15616SRichard Henderson } 296184f15616SRichard Henderson 2962e6d86bedSEmilio G. Cota plugin_gen_disable_mem_helpers(); 29635dd48602SRichard Henderson ptr = tcg_temp_ebb_new_ptr(); 2964ad75a51eSRichard Henderson gen_helper_lookup_tb_ptr(ptr, tcg_env); 2965ae8b75dcSRichard Henderson tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr)); 2966cedbcb01SEmilio G. Cota tcg_temp_free_ptr(ptr); 2967cedbcb01SEmilio G. Cota } 2968