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" 2633c11879SPaolo Bonzini #include "qemu-common.h" 2733c11879SPaolo Bonzini #include "cpu.h" 2863c91552SPaolo Bonzini #include "exec/exec-all.h" 29951c6300SRichard Henderson #include "tcg.h" 30951c6300SRichard Henderson #include "tcg-op.h" 31b32dc337SPranith Kumar #include "tcg-mo.h" 32dcdaadb6SLluís Vilanova #include "trace-tcg.h" 33dcdaadb6SLluís Vilanova #include "trace/mem.h" 34951c6300SRichard Henderson 353a13c3f3SRichard Henderson /* Reduce the number of ifdefs below. This assumes that all uses of 363a13c3f3SRichard Henderson TCGV_HIGH and TCGV_LOW are properly protected by a conditional that 373a13c3f3SRichard Henderson the compiler can eliminate. */ 383a13c3f3SRichard Henderson #if TCG_TARGET_REG_BITS == 64 393a13c3f3SRichard Henderson extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64); 403a13c3f3SRichard Henderson extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64); 413a13c3f3SRichard Henderson #define TCGV_LOW TCGV_LOW_link_error 423a13c3f3SRichard Henderson #define TCGV_HIGH TCGV_HIGH_link_error 433a13c3f3SRichard Henderson #endif 44951c6300SRichard Henderson 45b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1) 46951c6300SRichard Henderson { 47b7e8b17aSRichard Henderson TCGOp *op = tcg_emit_op(opc); 4875e8b9b7SRichard Henderson op->args[0] = a1; 49951c6300SRichard Henderson } 50951c6300SRichard Henderson 51b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2) 52951c6300SRichard Henderson { 53b7e8b17aSRichard Henderson TCGOp *op = tcg_emit_op(opc); 5475e8b9b7SRichard Henderson op->args[0] = a1; 5575e8b9b7SRichard Henderson op->args[1] = a2; 56951c6300SRichard Henderson } 57951c6300SRichard Henderson 58b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3) 59951c6300SRichard Henderson { 60b7e8b17aSRichard Henderson TCGOp *op = tcg_emit_op(opc); 6175e8b9b7SRichard Henderson op->args[0] = a1; 6275e8b9b7SRichard Henderson op->args[1] = a2; 6375e8b9b7SRichard Henderson op->args[2] = a3; 64951c6300SRichard Henderson } 65951c6300SRichard Henderson 66b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4) 67951c6300SRichard Henderson { 68b7e8b17aSRichard Henderson TCGOp *op = tcg_emit_op(opc); 6975e8b9b7SRichard Henderson op->args[0] = a1; 7075e8b9b7SRichard Henderson op->args[1] = a2; 7175e8b9b7SRichard Henderson op->args[2] = a3; 7275e8b9b7SRichard Henderson op->args[3] = a4; 73951c6300SRichard Henderson } 74951c6300SRichard Henderson 75b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 76b7e8b17aSRichard Henderson TCGArg a4, TCGArg a5) 77951c6300SRichard Henderson { 78b7e8b17aSRichard Henderson TCGOp *op = tcg_emit_op(opc); 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; 84951c6300SRichard Henderson } 85951c6300SRichard Henderson 86b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 87b7e8b17aSRichard Henderson TCGArg a4, TCGArg a5, TCGArg a6) 88951c6300SRichard Henderson { 89b7e8b17aSRichard Henderson TCGOp *op = tcg_emit_op(opc); 9075e8b9b7SRichard Henderson op->args[0] = a1; 9175e8b9b7SRichard Henderson op->args[1] = a2; 9275e8b9b7SRichard Henderson op->args[2] = a3; 9375e8b9b7SRichard Henderson op->args[3] = a4; 9475e8b9b7SRichard Henderson op->args[4] = a5; 9575e8b9b7SRichard Henderson op->args[5] = a6; 96951c6300SRichard Henderson } 97951c6300SRichard Henderson 98f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type) 99f65e19bcSPranith Kumar { 100b1311c4aSEmilio G. Cota if (tcg_ctx->tb_cflags & CF_PARALLEL) { 101b7e8b17aSRichard Henderson tcg_gen_op1(INDEX_op_mb, mb_type); 102f65e19bcSPranith Kumar } 103f65e19bcSPranith Kumar } 104f65e19bcSPranith Kumar 105951c6300SRichard Henderson /* 32 bit ops */ 106951c6300SRichard Henderson 107951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 108951c6300SRichard Henderson { 109951c6300SRichard Henderson /* some cases can be optimized here */ 110951c6300SRichard Henderson if (arg2 == 0) { 111951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 112951c6300SRichard Henderson } else { 113951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 114951c6300SRichard Henderson tcg_gen_add_i32(ret, arg1, t0); 115951c6300SRichard Henderson tcg_temp_free_i32(t0); 116951c6300SRichard Henderson } 117951c6300SRichard Henderson } 118951c6300SRichard Henderson 119951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2) 120951c6300SRichard Henderson { 121951c6300SRichard Henderson if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) { 122951c6300SRichard Henderson /* Don't recurse with tcg_gen_neg_i32. */ 123951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2); 124951c6300SRichard Henderson } else { 125951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg1); 126951c6300SRichard Henderson tcg_gen_sub_i32(ret, t0, arg2); 127951c6300SRichard Henderson tcg_temp_free_i32(t0); 128951c6300SRichard Henderson } 129951c6300SRichard Henderson } 130951c6300SRichard Henderson 131951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 132951c6300SRichard Henderson { 133951c6300SRichard Henderson /* some cases can be optimized here */ 134951c6300SRichard Henderson if (arg2 == 0) { 135951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 136951c6300SRichard Henderson } else { 137951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 138951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 139951c6300SRichard Henderson tcg_temp_free_i32(t0); 140951c6300SRichard Henderson } 141951c6300SRichard Henderson } 142951c6300SRichard Henderson 143474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 144951c6300SRichard Henderson { 145951c6300SRichard Henderson TCGv_i32 t0; 146951c6300SRichard Henderson /* Some cases can be optimized here. */ 147951c6300SRichard Henderson switch (arg2) { 148951c6300SRichard Henderson case 0: 149951c6300SRichard Henderson tcg_gen_movi_i32(ret, 0); 150951c6300SRichard Henderson return; 151474b2e8fSRichard Henderson case -1: 152951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 153951c6300SRichard Henderson return; 154474b2e8fSRichard Henderson case 0xff: 155951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i32. */ 156951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 157951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1); 158951c6300SRichard Henderson return; 159951c6300SRichard Henderson } 160951c6300SRichard Henderson break; 161474b2e8fSRichard Henderson case 0xffff: 162951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 163951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1); 164951c6300SRichard Henderson return; 165951c6300SRichard Henderson } 166951c6300SRichard Henderson break; 167951c6300SRichard Henderson } 168951c6300SRichard Henderson t0 = tcg_const_i32(arg2); 169951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, t0); 170951c6300SRichard Henderson tcg_temp_free_i32(t0); 171951c6300SRichard Henderson } 172951c6300SRichard Henderson 173951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 174951c6300SRichard Henderson { 175951c6300SRichard Henderson /* Some cases can be optimized here. */ 176951c6300SRichard Henderson if (arg2 == -1) { 177951c6300SRichard Henderson tcg_gen_movi_i32(ret, -1); 178951c6300SRichard Henderson } else if (arg2 == 0) { 179951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 180951c6300SRichard Henderson } else { 181951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 182951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, t0); 183951c6300SRichard Henderson tcg_temp_free_i32(t0); 184951c6300SRichard Henderson } 185951c6300SRichard Henderson } 186951c6300SRichard Henderson 187951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 188951c6300SRichard Henderson { 189951c6300SRichard Henderson /* Some cases can be optimized here. */ 190951c6300SRichard Henderson if (arg2 == 0) { 191951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 192951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) { 193951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i32. */ 194951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1); 195951c6300SRichard Henderson } else { 196951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 197951c6300SRichard Henderson tcg_gen_xor_i32(ret, arg1, t0); 198951c6300SRichard Henderson tcg_temp_free_i32(t0); 199951c6300SRichard Henderson } 200951c6300SRichard Henderson } 201951c6300SRichard Henderson 202474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 203951c6300SRichard Henderson { 204474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 205951c6300SRichard Henderson if (arg2 == 0) { 206951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 207951c6300SRichard Henderson } else { 208951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 209951c6300SRichard Henderson tcg_gen_shl_i32(ret, arg1, t0); 210951c6300SRichard Henderson tcg_temp_free_i32(t0); 211951c6300SRichard Henderson } 212951c6300SRichard Henderson } 213951c6300SRichard Henderson 214474b2e8fSRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 215951c6300SRichard Henderson { 216474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 217951c6300SRichard Henderson if (arg2 == 0) { 218951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 219951c6300SRichard Henderson } else { 220951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 221951c6300SRichard Henderson tcg_gen_shr_i32(ret, arg1, t0); 222951c6300SRichard Henderson tcg_temp_free_i32(t0); 223951c6300SRichard Henderson } 224951c6300SRichard Henderson } 225951c6300SRichard Henderson 226474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 227951c6300SRichard Henderson { 228474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 229951c6300SRichard Henderson if (arg2 == 0) { 230951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 231951c6300SRichard Henderson } else { 232951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 233951c6300SRichard Henderson tcg_gen_sar_i32(ret, arg1, t0); 234951c6300SRichard Henderson tcg_temp_free_i32(t0); 235951c6300SRichard Henderson } 236951c6300SRichard Henderson } 237951c6300SRichard Henderson 23842a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l) 239951c6300SRichard Henderson { 240951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 24142a268c2SRichard Henderson tcg_gen_br(l); 242951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 24342a268c2SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l)); 244951c6300SRichard Henderson } 245951c6300SRichard Henderson } 246951c6300SRichard Henderson 24742a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l) 248951c6300SRichard Henderson { 24937ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 25037ed3bf1SRichard Henderson tcg_gen_br(l); 25137ed3bf1SRichard Henderson } else if (cond != TCG_COND_NEVER) { 252951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 25342a268c2SRichard Henderson tcg_gen_brcond_i32(cond, arg1, t0, l); 254951c6300SRichard Henderson tcg_temp_free_i32(t0); 255951c6300SRichard Henderson } 25637ed3bf1SRichard Henderson } 257951c6300SRichard Henderson 258951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret, 259951c6300SRichard Henderson TCGv_i32 arg1, TCGv_i32 arg2) 260951c6300SRichard Henderson { 261951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 262951c6300SRichard Henderson tcg_gen_movi_i32(ret, 1); 263951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 264951c6300SRichard Henderson tcg_gen_movi_i32(ret, 0); 265951c6300SRichard Henderson } else { 266951c6300SRichard Henderson tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); 267951c6300SRichard Henderson } 268951c6300SRichard Henderson } 269951c6300SRichard Henderson 270951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, 271951c6300SRichard Henderson TCGv_i32 arg1, int32_t arg2) 272951c6300SRichard Henderson { 273951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 274951c6300SRichard Henderson tcg_gen_setcond_i32(cond, ret, arg1, t0); 275951c6300SRichard Henderson tcg_temp_free_i32(t0); 276951c6300SRichard Henderson } 277951c6300SRichard Henderson 278951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 279951c6300SRichard Henderson { 280b2e3ae94SRichard Henderson if (arg2 == 0) { 281b2e3ae94SRichard Henderson tcg_gen_movi_i32(ret, 0); 282b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 283b2e3ae94SRichard Henderson tcg_gen_shli_i32(ret, arg1, ctz32(arg2)); 284b2e3ae94SRichard Henderson } else { 285951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 286951c6300SRichard Henderson tcg_gen_mul_i32(ret, arg1, t0); 287951c6300SRichard Henderson tcg_temp_free_i32(t0); 288951c6300SRichard Henderson } 289b2e3ae94SRichard Henderson } 290951c6300SRichard Henderson 291951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 292951c6300SRichard Henderson { 293951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 294951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2); 295951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 296951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 297951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 298951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2); 299951c6300SRichard Henderson tcg_temp_free_i32(t0); 300951c6300SRichard Henderson } else { 301951c6300SRichard Henderson gen_helper_div_i32(ret, arg1, arg2); 302951c6300SRichard Henderson } 303951c6300SRichard Henderson } 304951c6300SRichard Henderson 305951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 306951c6300SRichard Henderson { 307951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 308951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2); 309951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 310951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 311951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2); 312951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 313951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 314951c6300SRichard Henderson tcg_temp_free_i32(t0); 315951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 316951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 317951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 318951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2); 319951c6300SRichard Henderson tcg_temp_free_i32(t0); 320951c6300SRichard Henderson } else { 321951c6300SRichard Henderson gen_helper_rem_i32(ret, arg1, arg2); 322951c6300SRichard Henderson } 323951c6300SRichard Henderson } 324951c6300SRichard Henderson 325951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 326951c6300SRichard Henderson { 327951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 328951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2); 329951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 330951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 331951c6300SRichard Henderson tcg_gen_movi_i32(t0, 0); 332951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2); 333951c6300SRichard Henderson tcg_temp_free_i32(t0); 334951c6300SRichard Henderson } else { 335951c6300SRichard Henderson gen_helper_divu_i32(ret, arg1, arg2); 336951c6300SRichard Henderson } 337951c6300SRichard Henderson } 338951c6300SRichard Henderson 339951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 340951c6300SRichard Henderson { 341951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 342951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); 343951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 344951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 345951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2); 346951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 347951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 348951c6300SRichard Henderson tcg_temp_free_i32(t0); 349951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 350951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 351951c6300SRichard Henderson tcg_gen_movi_i32(t0, 0); 352951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); 353951c6300SRichard Henderson tcg_temp_free_i32(t0); 354951c6300SRichard Henderson } else { 355951c6300SRichard Henderson gen_helper_remu_i32(ret, arg1, arg2); 356951c6300SRichard Henderson } 357951c6300SRichard Henderson } 358951c6300SRichard Henderson 359951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 360951c6300SRichard Henderson { 361951c6300SRichard Henderson if (TCG_TARGET_HAS_andc_i32) { 362951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2); 363951c6300SRichard Henderson } else { 364951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 365951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 366951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, t0); 367951c6300SRichard Henderson tcg_temp_free_i32(t0); 368951c6300SRichard Henderson } 369951c6300SRichard Henderson } 370951c6300SRichard Henderson 371951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 372951c6300SRichard Henderson { 373951c6300SRichard Henderson if (TCG_TARGET_HAS_eqv_i32) { 374951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2); 375951c6300SRichard Henderson } else { 376951c6300SRichard Henderson tcg_gen_xor_i32(ret, arg1, arg2); 377951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 378951c6300SRichard Henderson } 379951c6300SRichard Henderson } 380951c6300SRichard Henderson 381951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 382951c6300SRichard Henderson { 383951c6300SRichard Henderson if (TCG_TARGET_HAS_nand_i32) { 384951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2); 385951c6300SRichard Henderson } else { 386951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, arg2); 387951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 388951c6300SRichard Henderson } 389951c6300SRichard Henderson } 390951c6300SRichard Henderson 391951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 392951c6300SRichard Henderson { 393951c6300SRichard Henderson if (TCG_TARGET_HAS_nor_i32) { 394951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2); 395951c6300SRichard Henderson } else { 396951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, arg2); 397951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 398951c6300SRichard Henderson } 399951c6300SRichard Henderson } 400951c6300SRichard Henderson 401951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 402951c6300SRichard Henderson { 403951c6300SRichard Henderson if (TCG_TARGET_HAS_orc_i32) { 404951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2); 405951c6300SRichard Henderson } else { 406951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 407951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 408951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, t0); 409951c6300SRichard Henderson tcg_temp_free_i32(t0); 410951c6300SRichard Henderson } 411951c6300SRichard Henderson } 412951c6300SRichard Henderson 4130e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 4140e28d006SRichard Henderson { 4150e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 4160e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2); 4170e28d006SRichard Henderson } else if (TCG_TARGET_HAS_clz_i64) { 4180e28d006SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4190e28d006SRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4200e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 4210e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 4220e28d006SRichard Henderson tcg_gen_addi_i64(t2, t2, 32); 4230e28d006SRichard Henderson tcg_gen_clz_i64(t1, t1, t2); 4240e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 4250e28d006SRichard Henderson tcg_temp_free_i64(t1); 4260e28d006SRichard Henderson tcg_temp_free_i64(t2); 4270e28d006SRichard Henderson tcg_gen_subi_i32(ret, ret, 32); 4280e28d006SRichard Henderson } else { 4290e28d006SRichard Henderson gen_helper_clz_i32(ret, arg1, arg2); 4300e28d006SRichard Henderson } 4310e28d006SRichard Henderson } 4320e28d006SRichard Henderson 4330e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 4340e28d006SRichard Henderson { 4350e28d006SRichard Henderson TCGv_i32 t = tcg_const_i32(arg2); 4360e28d006SRichard Henderson tcg_gen_clz_i32(ret, arg1, t); 4370e28d006SRichard Henderson tcg_temp_free_i32(t); 4380e28d006SRichard Henderson } 4390e28d006SRichard Henderson 4400e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 4410e28d006SRichard Henderson { 4420e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i32) { 4430e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2); 4440e28d006SRichard Henderson } else if (TCG_TARGET_HAS_ctz_i64) { 4450e28d006SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4460e28d006SRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4470e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 4480e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 4490e28d006SRichard Henderson tcg_gen_ctz_i64(t1, t1, t2); 4500e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 4510e28d006SRichard Henderson tcg_temp_free_i64(t1); 4520e28d006SRichard Henderson tcg_temp_free_i64(t2); 45314e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i32 45414e99210SRichard Henderson || TCG_TARGET_HAS_ctpop_i64 45514e99210SRichard Henderson || TCG_TARGET_HAS_clz_i32 45614e99210SRichard Henderson || TCG_TARGET_HAS_clz_i64) { 45714e99210SRichard Henderson TCGv_i32 z, t = tcg_temp_new_i32(); 45814e99210SRichard Henderson 45914e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) { 46014e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 46114e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 46214e99210SRichard Henderson tcg_gen_ctpop_i32(t, t); 46314e99210SRichard Henderson } else { 46414e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 32, don't fight it. */ 46514e99210SRichard Henderson tcg_gen_neg_i32(t, arg1); 46614e99210SRichard Henderson tcg_gen_and_i32(t, t, arg1); 46714e99210SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 46814e99210SRichard Henderson tcg_gen_xori_i32(t, t, 31); 46914e99210SRichard Henderson } 47014e99210SRichard Henderson z = tcg_const_i32(0); 47114e99210SRichard Henderson tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t); 47214e99210SRichard Henderson tcg_temp_free_i32(t); 47314e99210SRichard Henderson tcg_temp_free_i32(z); 4740e28d006SRichard Henderson } else { 4750e28d006SRichard Henderson gen_helper_ctz_i32(ret, arg1, arg2); 4760e28d006SRichard Henderson } 4770e28d006SRichard Henderson } 4780e28d006SRichard Henderson 4790e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 4800e28d006SRichard Henderson { 48114e99210SRichard Henderson if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) { 48214e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 48314e99210SRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 48414e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 48514e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 48614e99210SRichard Henderson tcg_gen_ctpop_i32(ret, t); 48714e99210SRichard Henderson tcg_temp_free_i32(t); 48814e99210SRichard Henderson } else { 4890e28d006SRichard Henderson TCGv_i32 t = tcg_const_i32(arg2); 4900e28d006SRichard Henderson tcg_gen_ctz_i32(ret, arg1, t); 4910e28d006SRichard Henderson tcg_temp_free_i32(t); 4920e28d006SRichard Henderson } 49314e99210SRichard Henderson } 4940e28d006SRichard Henderson 495086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg) 496086920c2SRichard Henderson { 497086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 498086920c2SRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 499086920c2SRichard Henderson tcg_gen_sari_i32(t, arg, 31); 500086920c2SRichard Henderson tcg_gen_xor_i32(t, t, arg); 501086920c2SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 502086920c2SRichard Henderson tcg_gen_subi_i32(ret, t, 1); 503086920c2SRichard Henderson tcg_temp_free_i32(t); 504086920c2SRichard Henderson } else { 505086920c2SRichard Henderson gen_helper_clrsb_i32(ret, arg); 506086920c2SRichard Henderson } 507086920c2SRichard Henderson } 508086920c2SRichard Henderson 509a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1) 510a768e4e9SRichard Henderson { 511a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32) { 512a768e4e9SRichard Henderson tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1); 513a768e4e9SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64) { 514a768e4e9SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 515a768e4e9SRichard Henderson tcg_gen_extu_i32_i64(t, arg1); 516a768e4e9SRichard Henderson tcg_gen_ctpop_i64(t, t); 517a768e4e9SRichard Henderson tcg_gen_extrl_i64_i32(ret, t); 518a768e4e9SRichard Henderson tcg_temp_free_i64(t); 519a768e4e9SRichard Henderson } else { 520a768e4e9SRichard Henderson gen_helper_ctpop_i32(ret, arg1); 521a768e4e9SRichard Henderson } 522a768e4e9SRichard Henderson } 523a768e4e9SRichard Henderson 524951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 525951c6300SRichard Henderson { 526951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 527951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2); 528951c6300SRichard Henderson } else { 529951c6300SRichard Henderson TCGv_i32 t0, t1; 530951c6300SRichard Henderson 531951c6300SRichard Henderson t0 = tcg_temp_new_i32(); 532951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 533951c6300SRichard Henderson tcg_gen_shl_i32(t0, arg1, arg2); 534951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 535951c6300SRichard Henderson tcg_gen_shr_i32(t1, arg1, t1); 536951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 537951c6300SRichard Henderson tcg_temp_free_i32(t0); 538951c6300SRichard Henderson tcg_temp_free_i32(t1); 539951c6300SRichard Henderson } 540951c6300SRichard Henderson } 541951c6300SRichard Henderson 542951c6300SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2) 543951c6300SRichard Henderson { 544951c6300SRichard Henderson tcg_debug_assert(arg2 < 32); 545951c6300SRichard Henderson /* some cases can be optimized here */ 546951c6300SRichard Henderson if (arg2 == 0) { 547951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 548951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i32) { 549951c6300SRichard Henderson TCGv_i32 t0 = tcg_const_i32(arg2); 550951c6300SRichard Henderson tcg_gen_rotl_i32(ret, arg1, t0); 551951c6300SRichard Henderson tcg_temp_free_i32(t0); 552951c6300SRichard Henderson } else { 553951c6300SRichard Henderson TCGv_i32 t0, t1; 554951c6300SRichard Henderson t0 = tcg_temp_new_i32(); 555951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 556951c6300SRichard Henderson tcg_gen_shli_i32(t0, arg1, arg2); 557951c6300SRichard Henderson tcg_gen_shri_i32(t1, arg1, 32 - arg2); 558951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 559951c6300SRichard Henderson tcg_temp_free_i32(t0); 560951c6300SRichard Henderson tcg_temp_free_i32(t1); 561951c6300SRichard Henderson } 562951c6300SRichard Henderson } 563951c6300SRichard Henderson 564951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 565951c6300SRichard Henderson { 566951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 567951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2); 568951c6300SRichard Henderson } else { 569951c6300SRichard Henderson TCGv_i32 t0, t1; 570951c6300SRichard Henderson 571951c6300SRichard Henderson t0 = tcg_temp_new_i32(); 572951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 573951c6300SRichard Henderson tcg_gen_shr_i32(t0, arg1, arg2); 574951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 575951c6300SRichard Henderson tcg_gen_shl_i32(t1, arg1, t1); 576951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 577951c6300SRichard Henderson tcg_temp_free_i32(t0); 578951c6300SRichard Henderson tcg_temp_free_i32(t1); 579951c6300SRichard Henderson } 580951c6300SRichard Henderson } 581951c6300SRichard Henderson 582951c6300SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2) 583951c6300SRichard Henderson { 584951c6300SRichard Henderson tcg_debug_assert(arg2 < 32); 585951c6300SRichard Henderson /* some cases can be optimized here */ 586951c6300SRichard Henderson if (arg2 == 0) { 587951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 588951c6300SRichard Henderson } else { 589951c6300SRichard Henderson tcg_gen_rotli_i32(ret, arg1, 32 - arg2); 590951c6300SRichard Henderson } 591951c6300SRichard Henderson } 592951c6300SRichard Henderson 593951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, 594951c6300SRichard Henderson unsigned int ofs, unsigned int len) 595951c6300SRichard Henderson { 596951c6300SRichard Henderson uint32_t mask; 597951c6300SRichard Henderson TCGv_i32 t1; 598951c6300SRichard Henderson 599951c6300SRichard Henderson tcg_debug_assert(ofs < 32); 6000d0d309dSRichard Henderson tcg_debug_assert(len > 0); 601951c6300SRichard Henderson tcg_debug_assert(len <= 32); 602951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 32); 603951c6300SRichard Henderson 6040d0d309dSRichard Henderson if (len == 32) { 605951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg2); 606951c6300SRichard Henderson return; 607951c6300SRichard Henderson } 608951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) { 609951c6300SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); 610951c6300SRichard Henderson return; 611951c6300SRichard Henderson } 612951c6300SRichard Henderson 613951c6300SRichard Henderson mask = (1u << len) - 1; 614951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 615951c6300SRichard Henderson 616951c6300SRichard Henderson if (ofs + len < 32) { 617951c6300SRichard Henderson tcg_gen_andi_i32(t1, arg2, mask); 618951c6300SRichard Henderson tcg_gen_shli_i32(t1, t1, ofs); 619951c6300SRichard Henderson } else { 620951c6300SRichard Henderson tcg_gen_shli_i32(t1, arg2, ofs); 621951c6300SRichard Henderson } 622951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg1, ~(mask << ofs)); 623951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 624951c6300SRichard Henderson 625951c6300SRichard Henderson tcg_temp_free_i32(t1); 626951c6300SRichard Henderson } 627951c6300SRichard Henderson 62807cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, 62907cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 63007cc68d5SRichard Henderson { 63107cc68d5SRichard Henderson tcg_debug_assert(ofs < 32); 63207cc68d5SRichard Henderson tcg_debug_assert(len > 0); 63307cc68d5SRichard Henderson tcg_debug_assert(len <= 32); 63407cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 32); 63507cc68d5SRichard Henderson 63607cc68d5SRichard Henderson if (ofs + len == 32) { 63707cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 63807cc68d5SRichard Henderson } else if (ofs == 0) { 63907cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 64007cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i32 64107cc68d5SRichard Henderson && TCG_TARGET_deposit_i32_valid(ofs, len)) { 64207cc68d5SRichard Henderson TCGv_i32 zero = tcg_const_i32(0); 64307cc68d5SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); 64407cc68d5SRichard Henderson tcg_temp_free_i32(zero); 64507cc68d5SRichard Henderson } else { 64607cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 64707cc68d5SRichard Henderson which allows ARG to stay live. */ 64807cc68d5SRichard Henderson switch (len) { 64907cc68d5SRichard Henderson case 16: 65007cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 65107cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 65207cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 65307cc68d5SRichard Henderson return; 65407cc68d5SRichard Henderson } 65507cc68d5SRichard Henderson break; 65607cc68d5SRichard Henderson case 8: 65707cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 65807cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 65907cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 66007cc68d5SRichard Henderson return; 66107cc68d5SRichard Henderson } 66207cc68d5SRichard Henderson break; 66307cc68d5SRichard Henderson } 66407cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 66507cc68d5SRichard Henderson switch (ofs + len) { 66607cc68d5SRichard Henderson case 16: 66707cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 66807cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 66907cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, ret); 67007cc68d5SRichard Henderson return; 67107cc68d5SRichard Henderson } 67207cc68d5SRichard Henderson break; 67307cc68d5SRichard Henderson case 8: 67407cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 67507cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 67607cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, ret); 67707cc68d5SRichard Henderson return; 67807cc68d5SRichard Henderson } 67907cc68d5SRichard Henderson break; 68007cc68d5SRichard Henderson } 68107cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 68207cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 68307cc68d5SRichard Henderson } 68407cc68d5SRichard Henderson } 68507cc68d5SRichard Henderson 6867ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, 6877ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 6887ec8bab3SRichard Henderson { 6897ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 6907ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 6917ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 6927ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 6937ec8bab3SRichard Henderson 6947ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 6957ec8bab3SRichard Henderson if (ofs + len == 32) { 6967ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, 32 - len); 6977ec8bab3SRichard Henderson return; 6987ec8bab3SRichard Henderson } 6997ec8bab3SRichard Henderson if (ofs == 0) { 7007ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 7017ec8bab3SRichard Henderson return; 7027ec8bab3SRichard Henderson } 7037ec8bab3SRichard Henderson 7047ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i32 7057ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 7067ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len); 7077ec8bab3SRichard Henderson return; 7087ec8bab3SRichard Henderson } 7097ec8bab3SRichard Henderson 7107ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 7117ec8bab3SRichard Henderson switch (ofs + len) { 7127ec8bab3SRichard Henderson case 16: 7137ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 7147ec8bab3SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 7157ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 7167ec8bab3SRichard Henderson return; 7177ec8bab3SRichard Henderson } 7187ec8bab3SRichard Henderson break; 7197ec8bab3SRichard Henderson case 8: 7207ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 7217ec8bab3SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 7227ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 7237ec8bab3SRichard Henderson return; 7247ec8bab3SRichard Henderson } 7257ec8bab3SRichard Henderson break; 7267ec8bab3SRichard Henderson } 7277ec8bab3SRichard Henderson 7287ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 7297ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special case of 16, 7307ec8bab3SRichard Henderson so that we get ext8u, ext16u. */ 7317ec8bab3SRichard Henderson switch (len) { 7327ec8bab3SRichard Henderson case 1 ... 8: case 16: 7337ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 7347ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, ret, (1u << len) - 1); 7357ec8bab3SRichard Henderson break; 7367ec8bab3SRichard Henderson default: 7377ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 7387ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, 32 - len); 7397ec8bab3SRichard Henderson break; 7407ec8bab3SRichard Henderson } 7417ec8bab3SRichard Henderson } 7427ec8bab3SRichard Henderson 7437ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg, 7447ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 7457ec8bab3SRichard Henderson { 7467ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 7477ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 7487ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 7497ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 7507ec8bab3SRichard Henderson 7517ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 7527ec8bab3SRichard Henderson if (ofs + len == 32) { 7537ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, arg, 32 - len); 7547ec8bab3SRichard Henderson return; 7557ec8bab3SRichard Henderson } 7567ec8bab3SRichard Henderson if (ofs == 0) { 7577ec8bab3SRichard Henderson switch (len) { 7587ec8bab3SRichard Henderson case 16: 7597ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 7607ec8bab3SRichard Henderson return; 7617ec8bab3SRichard Henderson case 8: 7627ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 7637ec8bab3SRichard Henderson return; 7647ec8bab3SRichard Henderson } 7657ec8bab3SRichard Henderson } 7667ec8bab3SRichard Henderson 7677ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i32 7687ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 7697ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); 7707ec8bab3SRichard Henderson return; 7717ec8bab3SRichard Henderson } 7727ec8bab3SRichard Henderson 7737ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 7747ec8bab3SRichard Henderson switch (ofs + len) { 7757ec8bab3SRichard Henderson case 16: 7767ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 7777ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 7787ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 7797ec8bab3SRichard Henderson return; 7807ec8bab3SRichard Henderson } 7817ec8bab3SRichard Henderson break; 7827ec8bab3SRichard Henderson case 8: 7837ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 7847ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 7857ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 7867ec8bab3SRichard Henderson return; 7877ec8bab3SRichard Henderson } 7887ec8bab3SRichard Henderson break; 7897ec8bab3SRichard Henderson } 7907ec8bab3SRichard Henderson switch (len) { 7917ec8bab3SRichard Henderson case 16: 7927ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 7937ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 7947ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, ret); 7957ec8bab3SRichard Henderson return; 7967ec8bab3SRichard Henderson } 7977ec8bab3SRichard Henderson break; 7987ec8bab3SRichard Henderson case 8: 7997ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 8007ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 8017ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, ret); 8027ec8bab3SRichard Henderson return; 8037ec8bab3SRichard Henderson } 8047ec8bab3SRichard Henderson break; 8057ec8bab3SRichard Henderson } 8067ec8bab3SRichard Henderson 8077ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 8087ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, 32 - len); 8097ec8bab3SRichard Henderson } 8107ec8bab3SRichard Henderson 811951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, 812951c6300SRichard Henderson TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) 813951c6300SRichard Henderson { 81437ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 81537ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v1); 81637ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 81737ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v2); 81837ed3bf1SRichard Henderson } else if (TCG_TARGET_HAS_movcond_i32) { 819951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond); 820951c6300SRichard Henderson } else { 821951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 822951c6300SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 823951c6300SRichard Henderson tcg_gen_setcond_i32(cond, t0, c1, c2); 824951c6300SRichard Henderson tcg_gen_neg_i32(t0, t0); 825951c6300SRichard Henderson tcg_gen_and_i32(t1, v1, t0); 826951c6300SRichard Henderson tcg_gen_andc_i32(ret, v2, t0); 827951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 828951c6300SRichard Henderson tcg_temp_free_i32(t0); 829951c6300SRichard Henderson tcg_temp_free_i32(t1); 830951c6300SRichard Henderson } 831951c6300SRichard Henderson } 832951c6300SRichard Henderson 833951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 834951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 835951c6300SRichard Henderson { 836951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i32) { 837951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh); 838951c6300SRichard Henderson } else { 839951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 840951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 841951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 842951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 843951c6300SRichard Henderson tcg_gen_add_i64(t0, t0, t1); 844951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 845951c6300SRichard Henderson tcg_temp_free_i64(t0); 846951c6300SRichard Henderson tcg_temp_free_i64(t1); 847951c6300SRichard Henderson } 848951c6300SRichard Henderson } 849951c6300SRichard Henderson 850951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 851951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 852951c6300SRichard Henderson { 853951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i32) { 854951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh); 855951c6300SRichard Henderson } else { 856951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 857951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 858951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 859951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 860951c6300SRichard Henderson tcg_gen_sub_i64(t0, t0, t1); 861951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 862951c6300SRichard Henderson tcg_temp_free_i64(t0); 863951c6300SRichard Henderson tcg_temp_free_i64(t1); 864951c6300SRichard Henderson } 865951c6300SRichard Henderson } 866951c6300SRichard Henderson 867951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 868951c6300SRichard Henderson { 869951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i32) { 870951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); 871951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i32) { 872951c6300SRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 873951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 874951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2); 875951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 876951c6300SRichard Henderson tcg_temp_free_i32(t); 877951c6300SRichard Henderson } else { 878951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 879951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 880951c6300SRichard Henderson tcg_gen_extu_i32_i64(t0, arg1); 881951c6300SRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 882951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 883951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 884951c6300SRichard Henderson tcg_temp_free_i64(t0); 885951c6300SRichard Henderson tcg_temp_free_i64(t1); 886951c6300SRichard Henderson } 887951c6300SRichard Henderson } 888951c6300SRichard Henderson 889951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 890951c6300SRichard Henderson { 891951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i32) { 892951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); 893951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i32) { 894951c6300SRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 895951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 896951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2); 897951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 898951c6300SRichard Henderson tcg_temp_free_i32(t); 899951c6300SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 900951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 901951c6300SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 902951c6300SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 903951c6300SRichard Henderson TCGv_i32 t3 = tcg_temp_new_i32(); 904951c6300SRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 905951c6300SRichard Henderson /* Adjust for negative inputs. */ 906951c6300SRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 907951c6300SRichard Henderson tcg_gen_sari_i32(t3, arg2, 31); 908951c6300SRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 909951c6300SRichard Henderson tcg_gen_and_i32(t3, t3, arg1); 910951c6300SRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 911951c6300SRichard Henderson tcg_gen_sub_i32(rh, rh, t3); 912951c6300SRichard Henderson tcg_gen_mov_i32(rl, t0); 913951c6300SRichard Henderson tcg_temp_free_i32(t0); 914951c6300SRichard Henderson tcg_temp_free_i32(t1); 915951c6300SRichard Henderson tcg_temp_free_i32(t2); 916951c6300SRichard Henderson tcg_temp_free_i32(t3); 917951c6300SRichard Henderson } else { 918951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 919951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 920951c6300SRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 921951c6300SRichard Henderson tcg_gen_ext_i32_i64(t1, arg2); 922951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 923951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 924951c6300SRichard Henderson tcg_temp_free_i64(t0); 925951c6300SRichard Henderson tcg_temp_free_i64(t1); 926951c6300SRichard Henderson } 927951c6300SRichard Henderson } 928951c6300SRichard Henderson 9295087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 9305087abfbSRichard Henderson { 9315087abfbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 9325087abfbSRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 9335087abfbSRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 9345087abfbSRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 9355087abfbSRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 9365087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 9375087abfbSRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 9385087abfbSRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 9395087abfbSRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 9405087abfbSRichard Henderson tcg_gen_mov_i32(rl, t0); 9415087abfbSRichard Henderson tcg_temp_free_i32(t0); 9425087abfbSRichard Henderson tcg_temp_free_i32(t1); 9435087abfbSRichard Henderson tcg_temp_free_i32(t2); 9445087abfbSRichard Henderson } else { 9455087abfbSRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 9465087abfbSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 9475087abfbSRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 9485087abfbSRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 9495087abfbSRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 9505087abfbSRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 9515087abfbSRichard Henderson tcg_temp_free_i64(t0); 9525087abfbSRichard Henderson tcg_temp_free_i64(t1); 9535087abfbSRichard Henderson } 9545087abfbSRichard Henderson } 9555087abfbSRichard Henderson 956951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg) 957951c6300SRichard Henderson { 958951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 959951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg); 960951c6300SRichard Henderson } else { 961951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 24); 962951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 24); 963951c6300SRichard Henderson } 964951c6300SRichard Henderson } 965951c6300SRichard Henderson 966951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg) 967951c6300SRichard Henderson { 968951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 969951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg); 970951c6300SRichard Henderson } else { 971951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 16); 972951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 16); 973951c6300SRichard Henderson } 974951c6300SRichard Henderson } 975951c6300SRichard Henderson 976951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg) 977951c6300SRichard Henderson { 978951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 979951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg); 980951c6300SRichard Henderson } else { 981951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffu); 982951c6300SRichard Henderson } 983951c6300SRichard Henderson } 984951c6300SRichard Henderson 985951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg) 986951c6300SRichard Henderson { 987951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 988951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg); 989951c6300SRichard Henderson } else { 990951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffffu); 991951c6300SRichard Henderson } 992951c6300SRichard Henderson } 993951c6300SRichard Henderson 994951c6300SRichard Henderson /* Note: we assume the two high bytes are set to zero */ 995951c6300SRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg) 996951c6300SRichard Henderson { 997951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap16_i32) { 998951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg); 999951c6300SRichard Henderson } else { 1000951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 1001951c6300SRichard Henderson 1002951c6300SRichard Henderson tcg_gen_ext8u_i32(t0, arg); 1003951c6300SRichard Henderson tcg_gen_shli_i32(t0, t0, 8); 1004951c6300SRichard Henderson tcg_gen_shri_i32(ret, arg, 8); 1005951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t0); 1006951c6300SRichard Henderson tcg_temp_free_i32(t0); 1007951c6300SRichard Henderson } 1008951c6300SRichard Henderson } 1009951c6300SRichard Henderson 1010951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg) 1011951c6300SRichard Henderson { 1012951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap32_i32) { 1013951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg); 1014951c6300SRichard Henderson } else { 1015a686dc71SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 1016a686dc71SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 1017a686dc71SRichard Henderson TCGv_i32 t2 = tcg_const_i32(0x00ff00ff); 1018951c6300SRichard Henderson 1019a686dc71SRichard Henderson /* arg = abcd */ 1020a686dc71SRichard Henderson tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */ 1021a686dc71SRichard Henderson tcg_gen_and_i32(t1, arg, t2); /* t1 = .b.d */ 1022a686dc71SRichard Henderson tcg_gen_and_i32(t0, t0, t2); /* t0 = .a.c */ 1023a686dc71SRichard Henderson tcg_gen_shli_i32(t1, t1, 8); /* t1 = b.d. */ 1024a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = badc */ 1025951c6300SRichard Henderson 1026a686dc71SRichard Henderson tcg_gen_shri_i32(t0, ret, 16); /* t0 = ..ba */ 1027a686dc71SRichard Henderson tcg_gen_shli_i32(t1, ret, 16); /* t1 = dc.. */ 1028a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = dcba */ 1029951c6300SRichard Henderson 1030951c6300SRichard Henderson tcg_temp_free_i32(t0); 1031951c6300SRichard Henderson tcg_temp_free_i32(t1); 1032a686dc71SRichard Henderson tcg_temp_free_i32(t2); 1033951c6300SRichard Henderson } 1034951c6300SRichard Henderson } 1035951c6300SRichard Henderson 1036b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1037b87fb8cdSRichard Henderson { 1038b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); 1039b87fb8cdSRichard Henderson } 1040b87fb8cdSRichard Henderson 1041b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1042b87fb8cdSRichard Henderson { 1043b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); 1044b87fb8cdSRichard Henderson } 1045b87fb8cdSRichard Henderson 1046b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1047b87fb8cdSRichard Henderson { 1048b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); 1049b87fb8cdSRichard Henderson } 1050b87fb8cdSRichard Henderson 1051b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1052b87fb8cdSRichard Henderson { 1053b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); 1054b87fb8cdSRichard Henderson } 1055b87fb8cdSRichard Henderson 1056951c6300SRichard Henderson /* 64-bit ops */ 1057951c6300SRichard Henderson 1058951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32 1059951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64. */ 1060951c6300SRichard Henderson 1061951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg) 1062951c6300SRichard Henderson { 1063951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_LOW(arg)); 1064951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_HIGH(arg)); 1065951c6300SRichard Henderson } 1066951c6300SRichard Henderson 1067951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg) 1068951c6300SRichard Henderson { 1069951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1070951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 1071951c6300SRichard Henderson } 1072951c6300SRichard Henderson 1073951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 1074951c6300SRichard Henderson { 1075951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), arg); 1076951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32); 1077951c6300SRichard Henderson } 1078951c6300SRichard Henderson 1079951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1080951c6300SRichard Henderson { 1081951c6300SRichard Henderson tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset); 1082951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1083951c6300SRichard Henderson } 1084951c6300SRichard Henderson 1085951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1086951c6300SRichard Henderson { 1087951c6300SRichard Henderson tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset); 10883ff91d7eSJoseph Myers tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1089951c6300SRichard Henderson } 1090951c6300SRichard Henderson 1091951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1092951c6300SRichard Henderson { 1093951c6300SRichard Henderson tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset); 1094951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1095951c6300SRichard Henderson } 1096951c6300SRichard Henderson 1097951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1098951c6300SRichard Henderson { 1099951c6300SRichard Henderson tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset); 1100951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1101951c6300SRichard Henderson } 1102951c6300SRichard Henderson 1103951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1104951c6300SRichard Henderson { 1105951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1106951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1107951c6300SRichard Henderson } 1108951c6300SRichard Henderson 1109951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1110951c6300SRichard Henderson { 1111951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1112951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1113951c6300SRichard Henderson } 1114951c6300SRichard Henderson 1115951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1116951c6300SRichard Henderson { 1117951c6300SRichard Henderson /* Since arg2 and ret have different types, 1118951c6300SRichard Henderson they cannot be the same temporary */ 1119cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN 1120951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset); 1121951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4); 1122951c6300SRichard Henderson #else 1123951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1124951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4); 1125951c6300SRichard Henderson #endif 1126951c6300SRichard Henderson } 1127951c6300SRichard Henderson 1128951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1129951c6300SRichard Henderson { 1130cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN 1131951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset); 1132951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4); 1133951c6300SRichard Henderson #else 1134951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1135951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4); 1136951c6300SRichard Henderson #endif 1137951c6300SRichard Henderson } 1138951c6300SRichard Henderson 1139951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1140951c6300SRichard Henderson { 1141951c6300SRichard Henderson tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1142951c6300SRichard Henderson tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1143951c6300SRichard Henderson } 1144951c6300SRichard Henderson 1145951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1146951c6300SRichard Henderson { 1147951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1148951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1149951c6300SRichard Henderson } 1150951c6300SRichard Henderson 1151951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1152951c6300SRichard Henderson { 1153951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1154951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1155951c6300SRichard Henderson } 1156951c6300SRichard Henderson 1157951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1158951c6300SRichard Henderson { 1159951c6300SRichard Henderson gen_helper_shl_i64(ret, arg1, arg2); 1160951c6300SRichard Henderson } 1161951c6300SRichard Henderson 1162951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1163951c6300SRichard Henderson { 1164951c6300SRichard Henderson gen_helper_shr_i64(ret, arg1, arg2); 1165951c6300SRichard Henderson } 1166951c6300SRichard Henderson 1167951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1168951c6300SRichard Henderson { 1169951c6300SRichard Henderson gen_helper_sar_i64(ret, arg1, arg2); 1170951c6300SRichard Henderson } 1171951c6300SRichard Henderson 1172951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1173951c6300SRichard Henderson { 1174951c6300SRichard Henderson TCGv_i64 t0; 1175951c6300SRichard Henderson TCGv_i32 t1; 1176951c6300SRichard Henderson 1177951c6300SRichard Henderson t0 = tcg_temp_new_i64(); 1178951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 1179951c6300SRichard Henderson 1180951c6300SRichard Henderson tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0), 1181951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_LOW(arg2)); 1182951c6300SRichard Henderson 1183951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); 1184951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1185951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2)); 1186951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1187951c6300SRichard Henderson 1188951c6300SRichard Henderson tcg_gen_mov_i64(ret, t0); 1189951c6300SRichard Henderson tcg_temp_free_i64(t0); 1190951c6300SRichard Henderson tcg_temp_free_i32(t1); 1191951c6300SRichard Henderson } 1192951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */ 1193951c6300SRichard Henderson 1194951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1195951c6300SRichard Henderson { 1196951c6300SRichard Henderson /* some cases can be optimized here */ 1197951c6300SRichard Henderson if (arg2 == 0) { 1198951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1199951c6300SRichard Henderson } else { 1200951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1201951c6300SRichard Henderson tcg_gen_add_i64(ret, arg1, t0); 1202951c6300SRichard Henderson tcg_temp_free_i64(t0); 1203951c6300SRichard Henderson } 1204951c6300SRichard Henderson } 1205951c6300SRichard Henderson 1206951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2) 1207951c6300SRichard Henderson { 1208951c6300SRichard Henderson if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) { 1209951c6300SRichard Henderson /* Don't recurse with tcg_gen_neg_i64. */ 1210951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2); 1211951c6300SRichard Henderson } else { 1212951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg1); 1213951c6300SRichard Henderson tcg_gen_sub_i64(ret, t0, arg2); 1214951c6300SRichard Henderson tcg_temp_free_i64(t0); 1215951c6300SRichard Henderson } 1216951c6300SRichard Henderson } 1217951c6300SRichard Henderson 1218951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1219951c6300SRichard Henderson { 1220951c6300SRichard Henderson /* some cases can be optimized here */ 1221951c6300SRichard Henderson if (arg2 == 0) { 1222951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1223951c6300SRichard Henderson } else { 1224951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1225951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1226951c6300SRichard Henderson tcg_temp_free_i64(t0); 1227951c6300SRichard Henderson } 1228951c6300SRichard Henderson } 1229951c6300SRichard Henderson 1230474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1231951c6300SRichard Henderson { 12323a13c3f3SRichard Henderson TCGv_i64 t0; 12333a13c3f3SRichard Henderson 12343a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1235951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1236951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 12373a13c3f3SRichard Henderson return; 12383a13c3f3SRichard Henderson } 12393a13c3f3SRichard Henderson 1240951c6300SRichard Henderson /* Some cases can be optimized here. */ 1241951c6300SRichard Henderson switch (arg2) { 1242951c6300SRichard Henderson case 0: 1243951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1244951c6300SRichard Henderson return; 1245474b2e8fSRichard Henderson case -1: 1246951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1247951c6300SRichard Henderson return; 1248474b2e8fSRichard Henderson case 0xff: 1249951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i64. */ 1250951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 1251951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1); 1252951c6300SRichard Henderson return; 1253951c6300SRichard Henderson } 1254951c6300SRichard Henderson break; 1255474b2e8fSRichard Henderson case 0xffff: 1256951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 1257951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1); 1258951c6300SRichard Henderson return; 1259951c6300SRichard Henderson } 1260951c6300SRichard Henderson break; 1261474b2e8fSRichard Henderson case 0xffffffffu: 1262951c6300SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 1263951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1); 1264951c6300SRichard Henderson return; 1265951c6300SRichard Henderson } 1266951c6300SRichard Henderson break; 1267951c6300SRichard Henderson } 1268951c6300SRichard Henderson t0 = tcg_const_i64(arg2); 1269951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, t0); 1270951c6300SRichard Henderson tcg_temp_free_i64(t0); 1271951c6300SRichard Henderson } 1272951c6300SRichard Henderson 1273951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1274951c6300SRichard Henderson { 12753a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1276951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1277951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 12783a13c3f3SRichard Henderson return; 12793a13c3f3SRichard Henderson } 1280951c6300SRichard Henderson /* Some cases can be optimized here. */ 1281951c6300SRichard Henderson if (arg2 == -1) { 1282951c6300SRichard Henderson tcg_gen_movi_i64(ret, -1); 1283951c6300SRichard Henderson } else if (arg2 == 0) { 1284951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1285951c6300SRichard Henderson } else { 1286951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1287951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, t0); 1288951c6300SRichard Henderson tcg_temp_free_i64(t0); 1289951c6300SRichard Henderson } 1290951c6300SRichard Henderson } 1291951c6300SRichard Henderson 1292951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1293951c6300SRichard Henderson { 12943a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1295951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1296951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 12973a13c3f3SRichard Henderson return; 12983a13c3f3SRichard Henderson } 1299951c6300SRichard Henderson /* Some cases can be optimized here. */ 1300951c6300SRichard Henderson if (arg2 == 0) { 1301951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1302951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) { 1303951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i64. */ 1304951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1); 1305951c6300SRichard Henderson } else { 1306951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1307951c6300SRichard Henderson tcg_gen_xor_i64(ret, arg1, t0); 1308951c6300SRichard Henderson tcg_temp_free_i64(t0); 1309951c6300SRichard Henderson } 1310951c6300SRichard Henderson } 1311951c6300SRichard Henderson 1312951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, 1313951c6300SRichard Henderson unsigned c, bool right, bool arith) 1314951c6300SRichard Henderson { 1315951c6300SRichard Henderson tcg_debug_assert(c < 64); 1316951c6300SRichard Henderson if (c == 0) { 1317951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1318951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1319951c6300SRichard Henderson } else if (c >= 32) { 1320951c6300SRichard Henderson c -= 32; 1321951c6300SRichard Henderson if (right) { 1322951c6300SRichard Henderson if (arith) { 1323951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1324951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); 1325951c6300SRichard Henderson } else { 1326951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1327951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1328951c6300SRichard Henderson } 1329951c6300SRichard Henderson } else { 1330951c6300SRichard Henderson tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c); 1331951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 1332951c6300SRichard Henderson } 1333951c6300SRichard Henderson } else { 1334951c6300SRichard Henderson TCGv_i32 t0, t1; 1335951c6300SRichard Henderson 1336951c6300SRichard Henderson t0 = tcg_temp_new_i32(); 1337951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 1338951c6300SRichard Henderson if (right) { 1339951c6300SRichard Henderson tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c); 1340951c6300SRichard Henderson if (arith) { 1341951c6300SRichard Henderson tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c); 1342951c6300SRichard Henderson } else { 1343951c6300SRichard Henderson tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c); 1344951c6300SRichard Henderson } 1345951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 1346951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0); 1347951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t1); 1348951c6300SRichard Henderson } else { 1349951c6300SRichard Henderson tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c); 1350951c6300SRichard Henderson /* Note: ret can be the same as arg1, so we use t1 */ 1351951c6300SRichard Henderson tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c); 1352951c6300SRichard Henderson tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 1353951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0); 1354951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), t1); 1355951c6300SRichard Henderson } 1356951c6300SRichard Henderson tcg_temp_free_i32(t0); 1357951c6300SRichard Henderson tcg_temp_free_i32(t1); 1358951c6300SRichard Henderson } 1359951c6300SRichard Henderson } 1360951c6300SRichard Henderson 1361474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1362951c6300SRichard Henderson { 1363474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 13643a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 13653a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0); 13663a13c3f3SRichard Henderson } else if (arg2 == 0) { 1367951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1368951c6300SRichard Henderson } else { 1369951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1370951c6300SRichard Henderson tcg_gen_shl_i64(ret, arg1, t0); 1371951c6300SRichard Henderson tcg_temp_free_i64(t0); 1372951c6300SRichard Henderson } 1373951c6300SRichard Henderson } 1374951c6300SRichard Henderson 1375474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1376951c6300SRichard Henderson { 1377474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 13783a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 13793a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0); 13803a13c3f3SRichard Henderson } else if (arg2 == 0) { 1381951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1382951c6300SRichard Henderson } else { 1383951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1384951c6300SRichard Henderson tcg_gen_shr_i64(ret, arg1, t0); 1385951c6300SRichard Henderson tcg_temp_free_i64(t0); 1386951c6300SRichard Henderson } 1387951c6300SRichard Henderson } 1388951c6300SRichard Henderson 1389474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1390951c6300SRichard Henderson { 1391474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 13923a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 13933a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1); 13943a13c3f3SRichard Henderson } else if (arg2 == 0) { 1395951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1396951c6300SRichard Henderson } else { 1397951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1398951c6300SRichard Henderson tcg_gen_sar_i64(ret, arg1, t0); 1399951c6300SRichard Henderson tcg_temp_free_i64(t0); 1400951c6300SRichard Henderson } 1401951c6300SRichard Henderson } 1402951c6300SRichard Henderson 140342a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l) 1404951c6300SRichard Henderson { 1405951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 140642a268c2SRichard Henderson tcg_gen_br(l); 1407951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 14083a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1409951c6300SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1), 1410951c6300SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), 141142a268c2SRichard Henderson TCGV_HIGH(arg2), cond, label_arg(l)); 14123a13c3f3SRichard Henderson } else { 141342a268c2SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, 141442a268c2SRichard Henderson label_arg(l)); 14153a13c3f3SRichard Henderson } 1416951c6300SRichard Henderson } 1417951c6300SRichard Henderson } 1418951c6300SRichard Henderson 141942a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l) 1420951c6300SRichard Henderson { 1421951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 142242a268c2SRichard Henderson tcg_gen_br(l); 1423951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 1424951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 142542a268c2SRichard Henderson tcg_gen_brcond_i64(cond, arg1, t0, l); 1426951c6300SRichard Henderson tcg_temp_free_i64(t0); 1427951c6300SRichard Henderson } 1428951c6300SRichard Henderson } 1429951c6300SRichard Henderson 1430951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, 1431951c6300SRichard Henderson TCGv_i64 arg1, TCGv_i64 arg2) 1432951c6300SRichard Henderson { 1433951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 1434951c6300SRichard Henderson tcg_gen_movi_i64(ret, 1); 1435951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 1436951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1437951c6300SRichard Henderson } else { 14383a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1439951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 1440951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 1441951c6300SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 1442951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 14433a13c3f3SRichard Henderson } else { 1444951c6300SRichard Henderson tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); 14453a13c3f3SRichard Henderson } 1446951c6300SRichard Henderson } 1447951c6300SRichard Henderson } 1448951c6300SRichard Henderson 1449951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, 1450951c6300SRichard Henderson TCGv_i64 arg1, int64_t arg2) 1451951c6300SRichard Henderson { 1452951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1453951c6300SRichard Henderson tcg_gen_setcond_i64(cond, ret, arg1, t0); 1454951c6300SRichard Henderson tcg_temp_free_i64(t0); 1455951c6300SRichard Henderson } 1456951c6300SRichard Henderson 1457951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1458951c6300SRichard Henderson { 1459b2e3ae94SRichard Henderson if (arg2 == 0) { 1460b2e3ae94SRichard Henderson tcg_gen_movi_i64(ret, 0); 1461b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 1462b2e3ae94SRichard Henderson tcg_gen_shli_i64(ret, arg1, ctz64(arg2)); 1463b2e3ae94SRichard Henderson } else { 1464951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1465951c6300SRichard Henderson tcg_gen_mul_i64(ret, arg1, t0); 1466951c6300SRichard Henderson tcg_temp_free_i64(t0); 1467951c6300SRichard Henderson } 1468b2e3ae94SRichard Henderson } 1469951c6300SRichard Henderson 1470951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1471951c6300SRichard Henderson { 1472951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 1473951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2); 1474951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 1475951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1476951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 1477951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2); 1478951c6300SRichard Henderson tcg_temp_free_i64(t0); 1479951c6300SRichard Henderson } else { 1480951c6300SRichard Henderson gen_helper_div_i64(ret, arg1, arg2); 1481951c6300SRichard Henderson } 1482951c6300SRichard Henderson } 1483951c6300SRichard Henderson 1484951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1485951c6300SRichard Henderson { 1486951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 1487951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2); 1488951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 1489951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1490951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2); 1491951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 1492951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1493951c6300SRichard Henderson tcg_temp_free_i64(t0); 1494951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 1495951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1496951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 1497951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2); 1498951c6300SRichard Henderson tcg_temp_free_i64(t0); 1499951c6300SRichard Henderson } else { 1500951c6300SRichard Henderson gen_helper_rem_i64(ret, arg1, arg2); 1501951c6300SRichard Henderson } 1502951c6300SRichard Henderson } 1503951c6300SRichard Henderson 1504951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1505951c6300SRichard Henderson { 1506951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 1507951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2); 1508951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 1509951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1510951c6300SRichard Henderson tcg_gen_movi_i64(t0, 0); 1511951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2); 1512951c6300SRichard Henderson tcg_temp_free_i64(t0); 1513951c6300SRichard Henderson } else { 1514951c6300SRichard Henderson gen_helper_divu_i64(ret, arg1, arg2); 1515951c6300SRichard Henderson } 1516951c6300SRichard Henderson } 1517951c6300SRichard Henderson 1518951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1519951c6300SRichard Henderson { 1520951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 1521951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); 1522951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 1523951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1524951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2); 1525951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 1526951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 1527951c6300SRichard Henderson tcg_temp_free_i64(t0); 1528951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 1529951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1530951c6300SRichard Henderson tcg_gen_movi_i64(t0, 0); 1531951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); 1532951c6300SRichard Henderson tcg_temp_free_i64(t0); 1533951c6300SRichard Henderson } else { 1534951c6300SRichard Henderson gen_helper_remu_i64(ret, arg1, arg2); 1535951c6300SRichard Henderson } 1536951c6300SRichard Henderson } 1537951c6300SRichard Henderson 1538951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg) 1539951c6300SRichard Henderson { 15403a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1541951c6300SRichard Henderson tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1542951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 15433a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8s_i64) { 1544951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg); 1545951c6300SRichard Henderson } else { 1546951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 56); 1547951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 56); 1548951c6300SRichard Henderson } 1549951c6300SRichard Henderson } 1550951c6300SRichard Henderson 1551951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg) 1552951c6300SRichard Henderson { 15533a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1554951c6300SRichard Henderson tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1555951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 15563a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16s_i64) { 1557951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg); 1558951c6300SRichard Henderson } else { 1559951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 48); 1560951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 48); 1561951c6300SRichard Henderson } 1562951c6300SRichard Henderson } 1563951c6300SRichard Henderson 1564951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg) 1565951c6300SRichard Henderson { 15663a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1567951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1568951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 15693a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32s_i64) { 1570951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg); 1571951c6300SRichard Henderson } else { 1572951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 32); 1573951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 32); 1574951c6300SRichard Henderson } 1575951c6300SRichard Henderson } 1576951c6300SRichard Henderson 1577951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg) 1578951c6300SRichard Henderson { 15793a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1580951c6300SRichard Henderson tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1581951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 15823a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8u_i64) { 1583951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg); 1584951c6300SRichard Henderson } else { 1585951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffu); 1586951c6300SRichard Henderson } 1587951c6300SRichard Henderson } 1588951c6300SRichard Henderson 1589951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg) 1590951c6300SRichard Henderson { 15913a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1592951c6300SRichard Henderson tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1593951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 15943a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16u_i64) { 1595951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg); 1596951c6300SRichard Henderson } else { 1597951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffu); 1598951c6300SRichard Henderson } 1599951c6300SRichard Henderson } 1600951c6300SRichard Henderson 1601951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg) 1602951c6300SRichard Henderson { 16033a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1604951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1605951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 16063a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32u_i64) { 1607951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg); 1608951c6300SRichard Henderson } else { 1609951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffffffu); 1610951c6300SRichard Henderson } 1611951c6300SRichard Henderson } 1612951c6300SRichard Henderson 1613951c6300SRichard Henderson /* Note: we assume the six high bytes are set to zero */ 1614951c6300SRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg) 1615951c6300SRichard Henderson { 16163a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1617951c6300SRichard Henderson tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1618951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 16193a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap16_i64) { 1620951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg); 1621951c6300SRichard Henderson } else { 1622951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1623951c6300SRichard Henderson 1624951c6300SRichard Henderson tcg_gen_ext8u_i64(t0, arg); 1625951c6300SRichard Henderson tcg_gen_shli_i64(t0, t0, 8); 1626951c6300SRichard Henderson tcg_gen_shri_i64(ret, arg, 8); 1627951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t0); 1628951c6300SRichard Henderson tcg_temp_free_i64(t0); 1629951c6300SRichard Henderson } 1630951c6300SRichard Henderson } 1631951c6300SRichard Henderson 1632951c6300SRichard Henderson /* Note: we assume the four high bytes are set to zero */ 1633951c6300SRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg) 1634951c6300SRichard Henderson { 16353a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1636951c6300SRichard Henderson tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1637951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 16383a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap32_i64) { 1639951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg); 1640951c6300SRichard Henderson } else { 1641a686dc71SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1642a686dc71SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 1643a686dc71SRichard Henderson TCGv_i64 t2 = tcg_const_i64(0x00ff00ff); 1644951c6300SRichard Henderson 1645a686dc71SRichard Henderson /* arg = ....abcd */ 1646a686dc71SRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .....abc */ 1647a686dc71SRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */ 1648a686dc71SRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */ 1649a686dc71SRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */ 1650a686dc71SRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */ 1651951c6300SRichard Henderson 1652a686dc71SRichard Henderson tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */ 1653a686dc71SRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */ 1654a686dc71SRichard Henderson tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */ 1655a686dc71SRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = ....dcba */ 1656951c6300SRichard Henderson 1657951c6300SRichard Henderson tcg_temp_free_i64(t0); 1658951c6300SRichard Henderson tcg_temp_free_i64(t1); 1659a686dc71SRichard Henderson tcg_temp_free_i64(t2); 1660951c6300SRichard Henderson } 1661951c6300SRichard Henderson } 1662951c6300SRichard Henderson 1663951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg) 1664951c6300SRichard Henderson { 16653a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1666951c6300SRichard Henderson TCGv_i32 t0, t1; 1667951c6300SRichard Henderson t0 = tcg_temp_new_i32(); 1668951c6300SRichard Henderson t1 = tcg_temp_new_i32(); 1669951c6300SRichard Henderson 1670951c6300SRichard Henderson tcg_gen_bswap32_i32(t0, TCGV_LOW(arg)); 1671951c6300SRichard Henderson tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg)); 1672951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), t1); 1673951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t0); 1674951c6300SRichard Henderson tcg_temp_free_i32(t0); 1675951c6300SRichard Henderson tcg_temp_free_i32(t1); 16763a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap64_i64) { 1677951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg); 1678951c6300SRichard Henderson } else { 1679951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1680951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 16819e821eabSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 1682951c6300SRichard Henderson 16839e821eabSRichard Henderson /* arg = abcdefgh */ 16849e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull); 16859e821eabSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .abcdefg */ 16869e821eabSRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .b.d.f.h */ 16879e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .a.c.e.g */ 16889e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = b.d.f.h. */ 16899e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = badcfehg */ 1690951c6300SRichard Henderson 16919e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull); 16929e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ..badcfe */ 16939e821eabSRichard Henderson tcg_gen_and_i64(t1, ret, t2); /* t1 = ..dc..hg */ 16949e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = ..ba..fe */ 16959e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 16); /* t1 = dc..hg.. */ 16969e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = dcbahgfe */ 1697951c6300SRichard Henderson 16989e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 32); /* t0 = ....dcba */ 16999e821eabSRichard Henderson tcg_gen_shli_i64(t1, ret, 32); /* t1 = hgfe.... */ 17009e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = hgfedcba */ 1701951c6300SRichard Henderson 1702951c6300SRichard Henderson tcg_temp_free_i64(t0); 1703951c6300SRichard Henderson tcg_temp_free_i64(t1); 17049e821eabSRichard Henderson tcg_temp_free_i64(t2); 1705951c6300SRichard Henderson } 1706951c6300SRichard Henderson } 1707951c6300SRichard Henderson 1708951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg) 1709951c6300SRichard Henderson { 17103a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17113a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 17123a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 17133a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_not_i64) { 1714951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg); 1715951c6300SRichard Henderson } else { 1716951c6300SRichard Henderson tcg_gen_xori_i64(ret, arg, -1); 1717951c6300SRichard Henderson } 1718951c6300SRichard Henderson } 1719951c6300SRichard Henderson 1720951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1721951c6300SRichard Henderson { 17223a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17233a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 17243a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 17253a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_andc_i64) { 1726951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2); 1727951c6300SRichard Henderson } else { 1728951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1729951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 1730951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, t0); 1731951c6300SRichard Henderson tcg_temp_free_i64(t0); 1732951c6300SRichard Henderson } 1733951c6300SRichard Henderson } 1734951c6300SRichard Henderson 1735951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1736951c6300SRichard Henderson { 17373a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17383a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 17393a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 17403a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_eqv_i64) { 1741951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2); 1742951c6300SRichard Henderson } else { 1743951c6300SRichard Henderson tcg_gen_xor_i64(ret, arg1, arg2); 1744951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 1745951c6300SRichard Henderson } 1746951c6300SRichard Henderson } 1747951c6300SRichard Henderson 1748951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1749951c6300SRichard Henderson { 17503a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17513a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 17523a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 17533a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nand_i64) { 1754951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2); 1755951c6300SRichard Henderson } else { 1756951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, arg2); 1757951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 1758951c6300SRichard Henderson } 1759951c6300SRichard Henderson } 1760951c6300SRichard Henderson 1761951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1762951c6300SRichard Henderson { 17633a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17643a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 17653a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 17663a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nor_i64) { 1767951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2); 1768951c6300SRichard Henderson } else { 1769951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, arg2); 1770951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 1771951c6300SRichard Henderson } 1772951c6300SRichard Henderson } 1773951c6300SRichard Henderson 1774951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1775951c6300SRichard Henderson { 17763a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 17773a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 17783a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 17793a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_orc_i64) { 1780951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2); 1781951c6300SRichard Henderson } else { 1782951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 1783951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 1784951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, t0); 1785951c6300SRichard Henderson tcg_temp_free_i64(t0); 1786951c6300SRichard Henderson } 1787951c6300SRichard Henderson } 1788951c6300SRichard Henderson 17890e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 17900e28d006SRichard Henderson { 17910e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i64) { 17920e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2); 17930e28d006SRichard Henderson } else { 17940e28d006SRichard Henderson gen_helper_clz_i64(ret, arg1, arg2); 17950e28d006SRichard Henderson } 17960e28d006SRichard Henderson } 17970e28d006SRichard Henderson 17980e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 17990e28d006SRichard Henderson { 18000e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 18010e28d006SRichard Henderson && TCG_TARGET_HAS_clz_i32 18020e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 18030e28d006SRichard Henderson TCGv_i32 t = tcg_const_i32((uint32_t)arg2 - 32); 18040e28d006SRichard Henderson tcg_gen_clz_i32(t, TCGV_LOW(arg1), t); 18050e28d006SRichard Henderson tcg_gen_addi_i32(t, t, 32); 18060e28d006SRichard Henderson tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t); 18070e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 18080e28d006SRichard Henderson tcg_temp_free_i32(t); 18090e28d006SRichard Henderson } else { 18100e28d006SRichard Henderson TCGv_i64 t = tcg_const_i64(arg2); 18110e28d006SRichard Henderson tcg_gen_clz_i64(ret, arg1, t); 18120e28d006SRichard Henderson tcg_temp_free_i64(t); 18130e28d006SRichard Henderson } 18140e28d006SRichard Henderson } 18150e28d006SRichard Henderson 18160e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 18170e28d006SRichard Henderson { 18180e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i64) { 18190e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2); 182014e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) { 182114e99210SRichard Henderson TCGv_i64 z, t = tcg_temp_new_i64(); 182214e99210SRichard Henderson 182314e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 182414e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 182514e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 182614e99210SRichard Henderson tcg_gen_ctpop_i64(t, t); 182714e99210SRichard Henderson } else { 182814e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 64, don't fight it. */ 182914e99210SRichard Henderson tcg_gen_neg_i64(t, arg1); 183014e99210SRichard Henderson tcg_gen_and_i64(t, t, arg1); 183114e99210SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 183214e99210SRichard Henderson tcg_gen_xori_i64(t, t, 63); 183314e99210SRichard Henderson } 183414e99210SRichard Henderson z = tcg_const_i64(0); 183514e99210SRichard Henderson tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t); 183614e99210SRichard Henderson tcg_temp_free_i64(t); 183714e99210SRichard Henderson tcg_temp_free_i64(z); 18380e28d006SRichard Henderson } else { 18390e28d006SRichard Henderson gen_helper_ctz_i64(ret, arg1, arg2); 18400e28d006SRichard Henderson } 18410e28d006SRichard Henderson } 18420e28d006SRichard Henderson 18430e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 18440e28d006SRichard Henderson { 18450e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 18460e28d006SRichard Henderson && TCG_TARGET_HAS_ctz_i32 18470e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 18480e28d006SRichard Henderson TCGv_i32 t32 = tcg_const_i32((uint32_t)arg2 - 32); 18490e28d006SRichard Henderson tcg_gen_ctz_i32(t32, TCGV_HIGH(arg1), t32); 18500e28d006SRichard Henderson tcg_gen_addi_i32(t32, t32, 32); 18510e28d006SRichard Henderson tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32); 18520e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 18530e28d006SRichard Henderson tcg_temp_free_i32(t32); 185414e99210SRichard Henderson } else if (!TCG_TARGET_HAS_ctz_i64 185514e99210SRichard Henderson && TCG_TARGET_HAS_ctpop_i64 185614e99210SRichard Henderson && arg2 == 64) { 185714e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 185814e99210SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 185914e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 186014e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 186114e99210SRichard Henderson tcg_gen_ctpop_i64(ret, t); 186214e99210SRichard Henderson tcg_temp_free_i64(t); 18630e28d006SRichard Henderson } else { 18640e28d006SRichard Henderson TCGv_i64 t64 = tcg_const_i64(arg2); 18650e28d006SRichard Henderson tcg_gen_ctz_i64(ret, arg1, t64); 18660e28d006SRichard Henderson tcg_temp_free_i64(t64); 18670e28d006SRichard Henderson } 18680e28d006SRichard Henderson } 18690e28d006SRichard Henderson 1870086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg) 1871086920c2SRichard Henderson { 1872086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) { 1873086920c2SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 1874086920c2SRichard Henderson tcg_gen_sari_i64(t, arg, 63); 1875086920c2SRichard Henderson tcg_gen_xor_i64(t, t, arg); 1876086920c2SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 1877086920c2SRichard Henderson tcg_gen_subi_i64(ret, t, 1); 1878086920c2SRichard Henderson tcg_temp_free_i64(t); 1879086920c2SRichard Henderson } else { 1880086920c2SRichard Henderson gen_helper_clrsb_i64(ret, arg); 1881086920c2SRichard Henderson } 1882086920c2SRichard Henderson } 1883086920c2SRichard Henderson 1884a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1) 1885a768e4e9SRichard Henderson { 1886a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 1887a768e4e9SRichard Henderson tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1); 1888a768e4e9SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) { 1889a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1890a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1891a768e4e9SRichard Henderson tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret)); 1892a768e4e9SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1893a768e4e9SRichard Henderson } else { 1894a768e4e9SRichard Henderson gen_helper_ctpop_i64(ret, arg1); 1895a768e4e9SRichard Henderson } 1896a768e4e9SRichard Henderson } 1897a768e4e9SRichard Henderson 1898951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1899951c6300SRichard Henderson { 1900951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 1901951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2); 1902951c6300SRichard Henderson } else { 1903951c6300SRichard Henderson TCGv_i64 t0, t1; 1904951c6300SRichard Henderson t0 = tcg_temp_new_i64(); 1905951c6300SRichard Henderson t1 = tcg_temp_new_i64(); 1906951c6300SRichard Henderson tcg_gen_shl_i64(t0, arg1, arg2); 1907951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 1908951c6300SRichard Henderson tcg_gen_shr_i64(t1, arg1, t1); 1909951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 1910951c6300SRichard Henderson tcg_temp_free_i64(t0); 1911951c6300SRichard Henderson tcg_temp_free_i64(t1); 1912951c6300SRichard Henderson } 1913951c6300SRichard Henderson } 1914951c6300SRichard Henderson 1915951c6300SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2) 1916951c6300SRichard Henderson { 1917951c6300SRichard Henderson tcg_debug_assert(arg2 < 64); 1918951c6300SRichard Henderson /* some cases can be optimized here */ 1919951c6300SRichard Henderson if (arg2 == 0) { 1920951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1921951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i64) { 1922951c6300SRichard Henderson TCGv_i64 t0 = tcg_const_i64(arg2); 1923951c6300SRichard Henderson tcg_gen_rotl_i64(ret, arg1, t0); 1924951c6300SRichard Henderson tcg_temp_free_i64(t0); 1925951c6300SRichard Henderson } else { 1926951c6300SRichard Henderson TCGv_i64 t0, t1; 1927951c6300SRichard Henderson t0 = tcg_temp_new_i64(); 1928951c6300SRichard Henderson t1 = tcg_temp_new_i64(); 1929951c6300SRichard Henderson tcg_gen_shli_i64(t0, arg1, arg2); 1930951c6300SRichard Henderson tcg_gen_shri_i64(t1, arg1, 64 - arg2); 1931951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 1932951c6300SRichard Henderson tcg_temp_free_i64(t0); 1933951c6300SRichard Henderson tcg_temp_free_i64(t1); 1934951c6300SRichard Henderson } 1935951c6300SRichard Henderson } 1936951c6300SRichard Henderson 1937951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1938951c6300SRichard Henderson { 1939951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 1940951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2); 1941951c6300SRichard Henderson } else { 1942951c6300SRichard Henderson TCGv_i64 t0, t1; 1943951c6300SRichard Henderson t0 = tcg_temp_new_i64(); 1944951c6300SRichard Henderson t1 = tcg_temp_new_i64(); 1945951c6300SRichard Henderson tcg_gen_shr_i64(t0, arg1, arg2); 1946951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 1947951c6300SRichard Henderson tcg_gen_shl_i64(t1, arg1, t1); 1948951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 1949951c6300SRichard Henderson tcg_temp_free_i64(t0); 1950951c6300SRichard Henderson tcg_temp_free_i64(t1); 1951951c6300SRichard Henderson } 1952951c6300SRichard Henderson } 1953951c6300SRichard Henderson 1954951c6300SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2) 1955951c6300SRichard Henderson { 1956951c6300SRichard Henderson tcg_debug_assert(arg2 < 64); 1957951c6300SRichard Henderson /* some cases can be optimized here */ 1958951c6300SRichard Henderson if (arg2 == 0) { 1959951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1960951c6300SRichard Henderson } else { 1961951c6300SRichard Henderson tcg_gen_rotli_i64(ret, arg1, 64 - arg2); 1962951c6300SRichard Henderson } 1963951c6300SRichard Henderson } 1964951c6300SRichard Henderson 1965951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, 1966951c6300SRichard Henderson unsigned int ofs, unsigned int len) 1967951c6300SRichard Henderson { 1968951c6300SRichard Henderson uint64_t mask; 1969951c6300SRichard Henderson TCGv_i64 t1; 1970951c6300SRichard Henderson 1971951c6300SRichard Henderson tcg_debug_assert(ofs < 64); 19720d0d309dSRichard Henderson tcg_debug_assert(len > 0); 1973951c6300SRichard Henderson tcg_debug_assert(len <= 64); 1974951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 64); 1975951c6300SRichard Henderson 19760d0d309dSRichard Henderson if (len == 64) { 1977951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg2); 1978951c6300SRichard Henderson return; 1979951c6300SRichard Henderson } 1980951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) { 1981951c6300SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); 1982951c6300SRichard Henderson return; 1983951c6300SRichard Henderson } 1984951c6300SRichard Henderson 19853a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1986951c6300SRichard Henderson if (ofs >= 32) { 1987951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 1988951c6300SRichard Henderson TCGV_LOW(arg2), ofs - 32, len); 1989951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1990951c6300SRichard Henderson return; 1991951c6300SRichard Henderson } 1992951c6300SRichard Henderson if (ofs + len <= 32) { 1993951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1), 1994951c6300SRichard Henderson TCGV_LOW(arg2), ofs, len); 1995951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1996951c6300SRichard Henderson return; 1997951c6300SRichard Henderson } 19983a13c3f3SRichard Henderson } 1999951c6300SRichard Henderson 2000951c6300SRichard Henderson mask = (1ull << len) - 1; 2001951c6300SRichard Henderson t1 = tcg_temp_new_i64(); 2002951c6300SRichard Henderson 2003951c6300SRichard Henderson if (ofs + len < 64) { 2004951c6300SRichard Henderson tcg_gen_andi_i64(t1, arg2, mask); 2005951c6300SRichard Henderson tcg_gen_shli_i64(t1, t1, ofs); 2006951c6300SRichard Henderson } else { 2007951c6300SRichard Henderson tcg_gen_shli_i64(t1, arg2, ofs); 2008951c6300SRichard Henderson } 2009951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg1, ~(mask << ofs)); 2010951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2011951c6300SRichard Henderson 2012951c6300SRichard Henderson tcg_temp_free_i64(t1); 2013951c6300SRichard Henderson } 2014951c6300SRichard Henderson 201507cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, 201607cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 201707cc68d5SRichard Henderson { 201807cc68d5SRichard Henderson tcg_debug_assert(ofs < 64); 201907cc68d5SRichard Henderson tcg_debug_assert(len > 0); 202007cc68d5SRichard Henderson tcg_debug_assert(len <= 64); 202107cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 64); 202207cc68d5SRichard Henderson 202307cc68d5SRichard Henderson if (ofs + len == 64) { 202407cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 202507cc68d5SRichard Henderson } else if (ofs == 0) { 202607cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 202707cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i64 202807cc68d5SRichard Henderson && TCG_TARGET_deposit_i64_valid(ofs, len)) { 202907cc68d5SRichard Henderson TCGv_i64 zero = tcg_const_i64(0); 203007cc68d5SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); 203107cc68d5SRichard Henderson tcg_temp_free_i64(zero); 203207cc68d5SRichard Henderson } else { 203307cc68d5SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 203407cc68d5SRichard Henderson if (ofs >= 32) { 203507cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg), 203607cc68d5SRichard Henderson ofs - 32, len); 203707cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 203807cc68d5SRichard Henderson return; 203907cc68d5SRichard Henderson } 204007cc68d5SRichard Henderson if (ofs + len <= 32) { 204107cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 204207cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 204307cc68d5SRichard Henderson return; 204407cc68d5SRichard Henderson } 204507cc68d5SRichard Henderson } 204607cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 204707cc68d5SRichard Henderson which allows ARG to stay live. */ 204807cc68d5SRichard Henderson switch (len) { 204907cc68d5SRichard Henderson case 32: 205007cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 205107cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 205207cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 205307cc68d5SRichard Henderson return; 205407cc68d5SRichard Henderson } 205507cc68d5SRichard Henderson break; 205607cc68d5SRichard Henderson case 16: 205707cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 205807cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 205907cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 206007cc68d5SRichard Henderson return; 206107cc68d5SRichard Henderson } 206207cc68d5SRichard Henderson break; 206307cc68d5SRichard Henderson case 8: 206407cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 206507cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 206607cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 206707cc68d5SRichard Henderson return; 206807cc68d5SRichard Henderson } 206907cc68d5SRichard Henderson break; 207007cc68d5SRichard Henderson } 207107cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 207207cc68d5SRichard Henderson switch (ofs + len) { 207307cc68d5SRichard Henderson case 32: 207407cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 207507cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 207607cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, ret); 207707cc68d5SRichard Henderson return; 207807cc68d5SRichard Henderson } 207907cc68d5SRichard Henderson break; 208007cc68d5SRichard Henderson case 16: 208107cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 208207cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 208307cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, ret); 208407cc68d5SRichard Henderson return; 208507cc68d5SRichard Henderson } 208607cc68d5SRichard Henderson break; 208707cc68d5SRichard Henderson case 8: 208807cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 208907cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 209007cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, ret); 209107cc68d5SRichard Henderson return; 209207cc68d5SRichard Henderson } 209307cc68d5SRichard Henderson break; 209407cc68d5SRichard Henderson } 209507cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 209607cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 209707cc68d5SRichard Henderson } 209807cc68d5SRichard Henderson } 209907cc68d5SRichard Henderson 21007ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, 21017ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 21027ec8bab3SRichard Henderson { 21037ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 21047ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 21057ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 21067ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 21077ec8bab3SRichard Henderson 21087ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 21097ec8bab3SRichard Henderson if (ofs + len == 64) { 21107ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, 64 - len); 21117ec8bab3SRichard Henderson return; 21127ec8bab3SRichard Henderson } 21137ec8bab3SRichard Henderson if (ofs == 0) { 21147ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 21157ec8bab3SRichard Henderson return; 21167ec8bab3SRichard Henderson } 21177ec8bab3SRichard Henderson 21187ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 21197ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 21207ec8bab3SRichard Henderson if (ofs >= 32) { 21217ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 21227ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 21237ec8bab3SRichard Henderson return; 21247ec8bab3SRichard Henderson } 21257ec8bab3SRichard Henderson if (ofs + len <= 32) { 21267ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 21277ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 21287ec8bab3SRichard Henderson return; 21297ec8bab3SRichard Henderson } 21307ec8bab3SRichard Henderson /* The field is split across two words. One double-word 21317ec8bab3SRichard Henderson shift is better than two double-word shifts. */ 21327ec8bab3SRichard Henderson goto do_shift_and; 21337ec8bab3SRichard Henderson } 21347ec8bab3SRichard Henderson 21357ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i64 21367ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 21377ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len); 21387ec8bab3SRichard Henderson return; 21397ec8bab3SRichard Henderson } 21407ec8bab3SRichard Henderson 21417ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 21427ec8bab3SRichard Henderson switch (ofs + len) { 21437ec8bab3SRichard Henderson case 32: 21447ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 21457ec8bab3SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 21467ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 21477ec8bab3SRichard Henderson return; 21487ec8bab3SRichard Henderson } 21497ec8bab3SRichard Henderson break; 21507ec8bab3SRichard Henderson case 16: 21517ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 21527ec8bab3SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 21537ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 21547ec8bab3SRichard Henderson return; 21557ec8bab3SRichard Henderson } 21567ec8bab3SRichard Henderson break; 21577ec8bab3SRichard Henderson case 8: 21587ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 21597ec8bab3SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 21607ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 21617ec8bab3SRichard Henderson return; 21627ec8bab3SRichard Henderson } 21637ec8bab3SRichard Henderson break; 21647ec8bab3SRichard Henderson } 21657ec8bab3SRichard Henderson 21667ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 21677ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special cases of 16 and 32, 21687ec8bab3SRichard Henderson so that we get ext8u, ext16u, and ext32u. */ 21697ec8bab3SRichard Henderson switch (len) { 21707ec8bab3SRichard Henderson case 1 ... 8: case 16: case 32: 21717ec8bab3SRichard Henderson do_shift_and: 21727ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 21737ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, ret, (1ull << len) - 1); 21747ec8bab3SRichard Henderson break; 21757ec8bab3SRichard Henderson default: 21767ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 21777ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, 64 - len); 21787ec8bab3SRichard Henderson break; 21797ec8bab3SRichard Henderson } 21807ec8bab3SRichard Henderson } 21817ec8bab3SRichard Henderson 21827ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg, 21837ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 21847ec8bab3SRichard Henderson { 21857ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 21867ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 21877ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 21887ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 21897ec8bab3SRichard Henderson 21907ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if sextract is supported. */ 21917ec8bab3SRichard Henderson if (ofs + len == 64) { 21927ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, arg, 64 - len); 21937ec8bab3SRichard Henderson return; 21947ec8bab3SRichard Henderson } 21957ec8bab3SRichard Henderson if (ofs == 0) { 21967ec8bab3SRichard Henderson switch (len) { 21977ec8bab3SRichard Henderson case 32: 21987ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 21997ec8bab3SRichard Henderson return; 22007ec8bab3SRichard Henderson case 16: 22017ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 22027ec8bab3SRichard Henderson return; 22037ec8bab3SRichard Henderson case 8: 22047ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 22057ec8bab3SRichard Henderson return; 22067ec8bab3SRichard Henderson } 22077ec8bab3SRichard Henderson } 22087ec8bab3SRichard Henderson 22097ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 22107ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 22117ec8bab3SRichard Henderson if (ofs >= 32) { 22127ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 22137ec8bab3SRichard Henderson } else if (ofs + len <= 32) { 22147ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 22157ec8bab3SRichard Henderson } else if (ofs == 0) { 22167ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 22177ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32); 22187ec8bab3SRichard Henderson return; 22197ec8bab3SRichard Henderson } else if (len > 32) { 22207ec8bab3SRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 22217ec8bab3SRichard Henderson /* Extract the bits for the high word normally. */ 22227ec8bab3SRichard Henderson tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32); 22237ec8bab3SRichard Henderson /* Shift the field down for the low part. */ 22247ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 22257ec8bab3SRichard Henderson /* Overwrite the shift into the high part. */ 22267ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t); 22277ec8bab3SRichard Henderson tcg_temp_free_i32(t); 22287ec8bab3SRichard Henderson return; 22297ec8bab3SRichard Henderson } else { 22307ec8bab3SRichard Henderson /* Shift the field down for the low part, such that the 22317ec8bab3SRichard Henderson field sits at the MSB. */ 22327ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs + len - 32); 22337ec8bab3SRichard Henderson /* Shift the field down from the MSB, sign extending. */ 22347ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len); 22357ec8bab3SRichard Henderson } 22367ec8bab3SRichard Henderson /* Sign-extend the field from 32 bits. */ 22377ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 22387ec8bab3SRichard Henderson return; 22397ec8bab3SRichard Henderson } 22407ec8bab3SRichard Henderson 22417ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i64 22427ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 22437ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); 22447ec8bab3SRichard Henderson return; 22457ec8bab3SRichard Henderson } 22467ec8bab3SRichard Henderson 22477ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 22487ec8bab3SRichard Henderson switch (ofs + len) { 22497ec8bab3SRichard Henderson case 32: 22507ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 22517ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 22527ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 22537ec8bab3SRichard Henderson return; 22547ec8bab3SRichard Henderson } 22557ec8bab3SRichard Henderson break; 22567ec8bab3SRichard Henderson case 16: 22577ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 22587ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 22597ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 22607ec8bab3SRichard Henderson return; 22617ec8bab3SRichard Henderson } 22627ec8bab3SRichard Henderson break; 22637ec8bab3SRichard Henderson case 8: 22647ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 22657ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 22667ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 22677ec8bab3SRichard Henderson return; 22687ec8bab3SRichard Henderson } 22697ec8bab3SRichard Henderson break; 22707ec8bab3SRichard Henderson } 22717ec8bab3SRichard Henderson switch (len) { 22727ec8bab3SRichard Henderson case 32: 22737ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 22747ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 22757ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, ret); 22767ec8bab3SRichard Henderson return; 22777ec8bab3SRichard Henderson } 22787ec8bab3SRichard Henderson break; 22797ec8bab3SRichard Henderson case 16: 22807ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 22817ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 22827ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, ret); 22837ec8bab3SRichard Henderson return; 22847ec8bab3SRichard Henderson } 22857ec8bab3SRichard Henderson break; 22867ec8bab3SRichard Henderson case 8: 22877ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 22887ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 22897ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, ret); 22907ec8bab3SRichard Henderson return; 22917ec8bab3SRichard Henderson } 22927ec8bab3SRichard Henderson break; 22937ec8bab3SRichard Henderson } 22947ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 22957ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, 64 - len); 22967ec8bab3SRichard Henderson } 22977ec8bab3SRichard Henderson 2298951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, 2299951c6300SRichard Henderson TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2) 2300951c6300SRichard Henderson { 230137ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 230237ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v1); 230337ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 230437ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v2); 230537ed3bf1SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 2306951c6300SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 2307951c6300SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 2308951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, 2309951c6300SRichard Henderson TCGV_LOW(c1), TCGV_HIGH(c1), 2310951c6300SRichard Henderson TCGV_LOW(c2), TCGV_HIGH(c2), cond); 2311951c6300SRichard Henderson 2312951c6300SRichard Henderson if (TCG_TARGET_HAS_movcond_i32) { 2313951c6300SRichard Henderson tcg_gen_movi_i32(t1, 0); 2314951c6300SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1, 2315951c6300SRichard Henderson TCGV_LOW(v1), TCGV_LOW(v2)); 2316951c6300SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1, 2317951c6300SRichard Henderson TCGV_HIGH(v1), TCGV_HIGH(v2)); 2318951c6300SRichard Henderson } else { 2319951c6300SRichard Henderson tcg_gen_neg_i32(t0, t0); 2320951c6300SRichard Henderson 2321951c6300SRichard Henderson tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); 2322951c6300SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); 2323951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); 2324951c6300SRichard Henderson 2325951c6300SRichard Henderson tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); 2326951c6300SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); 2327951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); 2328951c6300SRichard Henderson } 2329951c6300SRichard Henderson tcg_temp_free_i32(t0); 2330951c6300SRichard Henderson tcg_temp_free_i32(t1); 23313a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_movcond_i64) { 2332951c6300SRichard Henderson tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); 2333951c6300SRichard Henderson } else { 2334951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 2335951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 2336951c6300SRichard Henderson tcg_gen_setcond_i64(cond, t0, c1, c2); 2337951c6300SRichard Henderson tcg_gen_neg_i64(t0, t0); 2338951c6300SRichard Henderson tcg_gen_and_i64(t1, v1, t0); 2339951c6300SRichard Henderson tcg_gen_andc_i64(ret, v2, t0); 2340951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2341951c6300SRichard Henderson tcg_temp_free_i64(t0); 2342951c6300SRichard Henderson tcg_temp_free_i64(t1); 2343951c6300SRichard Henderson } 2344951c6300SRichard Henderson } 2345951c6300SRichard Henderson 2346951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2347951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2348951c6300SRichard Henderson { 2349951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i64) { 2350951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh); 2351951c6300SRichard Henderson } else { 2352951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 2353951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 2354951c6300SRichard Henderson tcg_gen_add_i64(t0, al, bl); 2355951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al); 2356951c6300SRichard Henderson tcg_gen_add_i64(rh, ah, bh); 2357951c6300SRichard Henderson tcg_gen_add_i64(rh, rh, t1); 2358951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2359951c6300SRichard Henderson tcg_temp_free_i64(t0); 2360951c6300SRichard Henderson tcg_temp_free_i64(t1); 2361951c6300SRichard Henderson } 2362951c6300SRichard Henderson } 2363951c6300SRichard Henderson 2364951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 2365951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 2366951c6300SRichard Henderson { 2367951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i64) { 2368951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh); 2369951c6300SRichard Henderson } else { 2370951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 2371951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 2372951c6300SRichard Henderson tcg_gen_sub_i64(t0, al, bl); 2373951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl); 2374951c6300SRichard Henderson tcg_gen_sub_i64(rh, ah, bh); 2375951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t1); 2376951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2377951c6300SRichard Henderson tcg_temp_free_i64(t0); 2378951c6300SRichard Henderson tcg_temp_free_i64(t1); 2379951c6300SRichard Henderson } 2380951c6300SRichard Henderson } 2381951c6300SRichard Henderson 2382951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2383951c6300SRichard Henderson { 2384951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i64) { 2385951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); 2386951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i64) { 2387951c6300SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 2388951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2389951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2); 2390951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 2391951c6300SRichard Henderson tcg_temp_free_i64(t); 2392951c6300SRichard Henderson } else { 2393951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 2394951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 2395951c6300SRichard Henderson gen_helper_muluh_i64(rh, arg1, arg2); 2396951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2397951c6300SRichard Henderson tcg_temp_free_i64(t0); 2398951c6300SRichard Henderson } 2399951c6300SRichard Henderson } 2400951c6300SRichard Henderson 2401951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 2402951c6300SRichard Henderson { 2403951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i64) { 2404951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); 2405951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i64) { 2406951c6300SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 2407951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 2408951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2); 2409951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 2410951c6300SRichard Henderson tcg_temp_free_i64(t); 2411951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) { 2412951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 2413951c6300SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 2414951c6300SRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 2415951c6300SRichard Henderson TCGv_i64 t3 = tcg_temp_new_i64(); 2416951c6300SRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 2417951c6300SRichard Henderson /* Adjust for negative inputs. */ 2418951c6300SRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 2419951c6300SRichard Henderson tcg_gen_sari_i64(t3, arg2, 63); 2420951c6300SRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 2421951c6300SRichard Henderson tcg_gen_and_i64(t3, t3, arg1); 2422951c6300SRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 2423951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t3); 2424951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2425951c6300SRichard Henderson tcg_temp_free_i64(t0); 2426951c6300SRichard Henderson tcg_temp_free_i64(t1); 2427951c6300SRichard Henderson tcg_temp_free_i64(t2); 2428951c6300SRichard Henderson tcg_temp_free_i64(t3); 2429951c6300SRichard Henderson } else { 2430951c6300SRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 2431951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 2432951c6300SRichard Henderson gen_helper_mulsh_i64(rh, arg1, arg2); 2433951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 2434951c6300SRichard Henderson tcg_temp_free_i64(t0); 2435951c6300SRichard Henderson } 2436951c6300SRichard Henderson } 2437951c6300SRichard Henderson 24385087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 24395087abfbSRichard Henderson { 24405087abfbSRichard Henderson TCGv_i64 t0 = tcg_temp_new_i64(); 24415087abfbSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 24425087abfbSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 24435087abfbSRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 24445087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 24455087abfbSRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 24465087abfbSRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 24475087abfbSRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 24485087abfbSRichard Henderson tcg_gen_mov_i64(rl, t0); 24495087abfbSRichard Henderson tcg_temp_free_i64(t0); 24505087abfbSRichard Henderson tcg_temp_free_i64(t1); 24515087abfbSRichard Henderson tcg_temp_free_i64(t2); 24525087abfbSRichard Henderson } 24535087abfbSRichard Henderson 2454b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2455b87fb8cdSRichard Henderson { 2456b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); 2457b87fb8cdSRichard Henderson } 2458b87fb8cdSRichard Henderson 2459b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2460b87fb8cdSRichard Henderson { 2461b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); 2462b87fb8cdSRichard Henderson } 2463b87fb8cdSRichard Henderson 2464b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2465b87fb8cdSRichard Henderson { 2466b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); 2467b87fb8cdSRichard Henderson } 2468b87fb8cdSRichard Henderson 2469b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 2470b87fb8cdSRichard Henderson { 2471b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); 2472b87fb8cdSRichard Henderson } 2473b87fb8cdSRichard Henderson 2474951c6300SRichard Henderson /* Size changing operations. */ 2475951c6300SRichard Henderson 2476609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2477951c6300SRichard Henderson { 24783a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2479951c6300SRichard Henderson tcg_gen_mov_i32(ret, TCGV_LOW(arg)); 2480609ad705SRichard Henderson } else if (TCG_TARGET_HAS_extrl_i64_i32) { 2481b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrl_i64_i32, 2482ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2483951c6300SRichard Henderson } else { 2484dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)arg); 2485609ad705SRichard Henderson } 2486609ad705SRichard Henderson } 2487609ad705SRichard Henderson 2488609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 2489609ad705SRichard Henderson { 2490609ad705SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2491609ad705SRichard Henderson tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); 2492609ad705SRichard Henderson } else if (TCG_TARGET_HAS_extrh_i64_i32) { 2493b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrh_i64_i32, 2494ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 2495951c6300SRichard Henderson } else { 2496951c6300SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 2497609ad705SRichard Henderson tcg_gen_shri_i64(t, arg, 32); 2498dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)t); 2499951c6300SRichard Henderson tcg_temp_free_i64(t); 2500951c6300SRichard Henderson } 2501951c6300SRichard Henderson } 2502951c6300SRichard Henderson 2503951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2504951c6300SRichard Henderson { 25053a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2506951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2507951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 25083a13c3f3SRichard Henderson } else { 2509b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extu_i32_i64, 2510ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 25113a13c3f3SRichard Henderson } 2512951c6300SRichard Henderson } 2513951c6300SRichard Henderson 2514951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 2515951c6300SRichard Henderson { 25163a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2517951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 2518951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 25193a13c3f3SRichard Henderson } else { 2520b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_ext_i32_i64, 2521ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 25223a13c3f3SRichard Henderson } 2523951c6300SRichard Henderson } 2524951c6300SRichard Henderson 2525951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) 2526951c6300SRichard Henderson { 25273a13c3f3SRichard Henderson TCGv_i64 tmp; 25283a13c3f3SRichard Henderson 25293a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2530951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(dest), low); 2531951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(dest), high); 25323a13c3f3SRichard Henderson return; 25333a13c3f3SRichard Henderson } 25343a13c3f3SRichard Henderson 25353a13c3f3SRichard Henderson tmp = tcg_temp_new_i64(); 2536951c6300SRichard Henderson /* These extensions are only needed for type correctness. 2537951c6300SRichard Henderson We may be able to do better given target specific information. */ 2538951c6300SRichard Henderson tcg_gen_extu_i32_i64(tmp, high); 2539951c6300SRichard Henderson tcg_gen_extu_i32_i64(dest, low); 2540951c6300SRichard Henderson /* If deposit is available, use it. Otherwise use the extra 2541951c6300SRichard Henderson knowledge that we have of the zero-extensions above. */ 2542951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { 2543951c6300SRichard Henderson tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); 2544951c6300SRichard Henderson } else { 2545951c6300SRichard Henderson tcg_gen_shli_i64(tmp, tmp, 32); 2546951c6300SRichard Henderson tcg_gen_or_i64(dest, dest, tmp); 2547951c6300SRichard Henderson } 2548951c6300SRichard Henderson tcg_temp_free_i64(tmp); 2549951c6300SRichard Henderson } 2550951c6300SRichard Henderson 2551951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg) 2552951c6300SRichard Henderson { 25533a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2554951c6300SRichard Henderson tcg_gen_mov_i32(lo, TCGV_LOW(arg)); 2555951c6300SRichard Henderson tcg_gen_mov_i32(hi, TCGV_HIGH(arg)); 25563a13c3f3SRichard Henderson } else { 2557609ad705SRichard Henderson tcg_gen_extrl_i64_i32(lo, arg); 2558609ad705SRichard Henderson tcg_gen_extrh_i64_i32(hi, arg); 25593a13c3f3SRichard Henderson } 2560951c6300SRichard Henderson } 2561951c6300SRichard Henderson 2562951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) 2563951c6300SRichard Henderson { 2564951c6300SRichard Henderson tcg_gen_ext32u_i64(lo, arg); 2565951c6300SRichard Henderson tcg_gen_shri_i64(hi, arg, 32); 2566951c6300SRichard Henderson } 2567951c6300SRichard Henderson 2568951c6300SRichard Henderson /* QEMU specific operations. */ 2569951c6300SRichard Henderson 257007ea28b4SRichard Henderson void tcg_gen_exit_tb(TranslationBlock *tb, unsigned idx) 257107ea28b4SRichard Henderson { 257207ea28b4SRichard Henderson uintptr_t val = (uintptr_t)tb + idx; 257307ea28b4SRichard Henderson 257407ea28b4SRichard Henderson if (tb == NULL) { 257507ea28b4SRichard Henderson tcg_debug_assert(idx == 0); 257607ea28b4SRichard Henderson } else if (idx <= TB_EXIT_IDXMAX) { 257707ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG 257807ea28b4SRichard Henderson /* This is an exit following a goto_tb. Verify that we have 257907ea28b4SRichard Henderson seen this numbered exit before, via tcg_gen_goto_tb. */ 258007ea28b4SRichard Henderson tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); 258107ea28b4SRichard Henderson #endif 2582d7f425fdSRichard Henderson /* When not chaining, exit without indicating a link. */ 2583d7f425fdSRichard Henderson if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) { 2584d7f425fdSRichard Henderson val = 0; 2585d7f425fdSRichard Henderson } 258607ea28b4SRichard Henderson } else { 258707ea28b4SRichard Henderson /* This is an exit via the exitreq label. */ 258807ea28b4SRichard Henderson tcg_debug_assert(idx == TB_EXIT_REQUESTED); 258907ea28b4SRichard Henderson } 259007ea28b4SRichard Henderson 259107ea28b4SRichard Henderson tcg_gen_op1i(INDEX_op_exit_tb, val); 259207ea28b4SRichard Henderson } 259307ea28b4SRichard Henderson 2594951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx) 2595951c6300SRichard Henderson { 2596951c6300SRichard Henderson /* We only support two chained exits. */ 259707ea28b4SRichard Henderson tcg_debug_assert(idx <= TB_EXIT_IDXMAX); 2598951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG 2599951c6300SRichard Henderson /* Verify that we havn't seen this numbered exit before. */ 2600b1311c4aSEmilio G. Cota tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0); 2601b1311c4aSEmilio G. Cota tcg_ctx->goto_tb_issue_mask |= 1 << idx; 2602951c6300SRichard Henderson #endif 2603d7f425fdSRichard Henderson /* When not chaining, we simply fall through to the "fallback" exit. */ 2604d7f425fdSRichard Henderson if (!qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) { 2605951c6300SRichard Henderson tcg_gen_op1i(INDEX_op_goto_tb, idx); 2606951c6300SRichard Henderson } 2607d7f425fdSRichard Henderson } 2608951c6300SRichard Henderson 26097f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void) 2610cedbcb01SEmilio G. Cota { 2611cedbcb01SEmilio G. Cota if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) { 2612cedbcb01SEmilio G. Cota TCGv_ptr ptr = tcg_temp_new_ptr(); 26131c2adb95SRichard Henderson gen_helper_lookup_tb_ptr(ptr, cpu_env); 2614ae8b75dcSRichard Henderson tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr)); 2615cedbcb01SEmilio G. Cota tcg_temp_free_ptr(ptr); 2616cedbcb01SEmilio G. Cota } else { 261707ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 2618cedbcb01SEmilio G. Cota } 2619cedbcb01SEmilio G. Cota } 2620cedbcb01SEmilio G. Cota 2621951c6300SRichard Henderson static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st) 2622951c6300SRichard Henderson { 26231f00b27fSSergey Sorokin /* Trigger the asserts within as early as possible. */ 26241f00b27fSSergey Sorokin (void)get_alignment_bits(op); 26251f00b27fSSergey Sorokin 2626951c6300SRichard Henderson switch (op & MO_SIZE) { 2627951c6300SRichard Henderson case MO_8: 2628951c6300SRichard Henderson op &= ~MO_BSWAP; 2629951c6300SRichard Henderson break; 2630951c6300SRichard Henderson case MO_16: 2631951c6300SRichard Henderson break; 2632951c6300SRichard Henderson case MO_32: 2633951c6300SRichard Henderson if (!is64) { 2634951c6300SRichard Henderson op &= ~MO_SIGN; 2635951c6300SRichard Henderson } 2636951c6300SRichard Henderson break; 2637951c6300SRichard Henderson case MO_64: 2638951c6300SRichard Henderson if (!is64) { 2639951c6300SRichard Henderson tcg_abort(); 2640951c6300SRichard Henderson } 2641951c6300SRichard Henderson break; 2642951c6300SRichard Henderson } 2643951c6300SRichard Henderson if (st) { 2644951c6300SRichard Henderson op &= ~MO_SIGN; 2645951c6300SRichard Henderson } 2646951c6300SRichard Henderson return op; 2647951c6300SRichard Henderson } 2648951c6300SRichard Henderson 2649c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr, 2650c45cb8bbSRichard Henderson TCGMemOp memop, TCGArg idx) 2651951c6300SRichard Henderson { 265259227d5dSRichard Henderson TCGMemOpIdx oi = make_memop_idx(memop, idx); 2653951c6300SRichard Henderson #if TARGET_LONG_BITS == 32 265459227d5dSRichard Henderson tcg_gen_op3i_i32(opc, val, addr, oi); 2655951c6300SRichard Henderson #else 2656c45cb8bbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 265759227d5dSRichard Henderson tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi); 2658c45cb8bbSRichard Henderson } else { 2659ae8b75dcSRichard Henderson tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi); 2660c45cb8bbSRichard Henderson } 2661951c6300SRichard Henderson #endif 2662c45cb8bbSRichard Henderson } 2663c45cb8bbSRichard Henderson 2664c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr, 2665c45cb8bbSRichard Henderson TCGMemOp memop, TCGArg idx) 2666c45cb8bbSRichard Henderson { 266759227d5dSRichard Henderson TCGMemOpIdx oi = make_memop_idx(memop, idx); 2668c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32 2669c45cb8bbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 267059227d5dSRichard Henderson tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi); 2671c45cb8bbSRichard Henderson } else { 2672ae8b75dcSRichard Henderson tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi); 2673c45cb8bbSRichard Henderson } 2674c45cb8bbSRichard Henderson #else 2675c45cb8bbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 267659227d5dSRichard Henderson tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), 267759227d5dSRichard Henderson TCGV_LOW(addr), TCGV_HIGH(addr), oi); 2678c45cb8bbSRichard Henderson } else { 267959227d5dSRichard Henderson tcg_gen_op3i_i64(opc, val, addr, oi); 2680c45cb8bbSRichard Henderson } 2681c45cb8bbSRichard Henderson #endif 2682c45cb8bbSRichard Henderson } 2683951c6300SRichard Henderson 2684b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type) 2685b32dc337SPranith Kumar { 2686b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO 2687b32dc337SPranith Kumar type &= TCG_GUEST_DEFAULT_MO; 2688b32dc337SPranith Kumar #endif 2689b32dc337SPranith Kumar type &= ~TCG_TARGET_DEFAULT_MO; 2690b32dc337SPranith Kumar if (type) { 2691b32dc337SPranith Kumar tcg_gen_mb(type | TCG_BAR_SC); 2692b32dc337SPranith Kumar } 2693b32dc337SPranith Kumar } 2694b32dc337SPranith Kumar 2695951c6300SRichard Henderson void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop) 2696951c6300SRichard Henderson { 2697*e1dcf352SRichard Henderson TCGMemOp orig_memop; 2698*e1dcf352SRichard Henderson 2699b32dc337SPranith Kumar tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD); 2700951c6300SRichard Henderson memop = tcg_canonicalize_memop(memop, 0, 0); 27011c2adb95SRichard Henderson trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, 2702dcdaadb6SLluís Vilanova addr, trace_mem_get_info(memop, 0)); 2703*e1dcf352SRichard Henderson 2704*e1dcf352SRichard Henderson orig_memop = memop; 2705*e1dcf352SRichard Henderson if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 2706*e1dcf352SRichard Henderson memop &= ~MO_BSWAP; 2707*e1dcf352SRichard Henderson /* The bswap primitive requires zero-extended input. */ 2708*e1dcf352SRichard Henderson if ((memop & MO_SSIZE) == MO_SW) { 2709*e1dcf352SRichard Henderson memop &= ~MO_SIGN; 2710*e1dcf352SRichard Henderson } 2711*e1dcf352SRichard Henderson } 2712*e1dcf352SRichard Henderson 2713c45cb8bbSRichard Henderson gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx); 2714*e1dcf352SRichard Henderson 2715*e1dcf352SRichard Henderson if ((orig_memop ^ memop) & MO_BSWAP) { 2716*e1dcf352SRichard Henderson switch (orig_memop & MO_SIZE) { 2717*e1dcf352SRichard Henderson case MO_16: 2718*e1dcf352SRichard Henderson tcg_gen_bswap16_i32(val, val); 2719*e1dcf352SRichard Henderson if (orig_memop & MO_SIGN) { 2720*e1dcf352SRichard Henderson tcg_gen_ext16s_i32(val, val); 2721*e1dcf352SRichard Henderson } 2722*e1dcf352SRichard Henderson break; 2723*e1dcf352SRichard Henderson case MO_32: 2724*e1dcf352SRichard Henderson tcg_gen_bswap32_i32(val, val); 2725*e1dcf352SRichard Henderson break; 2726*e1dcf352SRichard Henderson default: 2727*e1dcf352SRichard Henderson g_assert_not_reached(); 2728*e1dcf352SRichard Henderson } 2729*e1dcf352SRichard Henderson } 2730951c6300SRichard Henderson } 2731951c6300SRichard Henderson 2732951c6300SRichard Henderson void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop) 2733951c6300SRichard Henderson { 2734*e1dcf352SRichard Henderson TCGv_i32 swap = NULL; 2735*e1dcf352SRichard Henderson 2736b32dc337SPranith Kumar tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST); 2737951c6300SRichard Henderson memop = tcg_canonicalize_memop(memop, 0, 1); 27381c2adb95SRichard Henderson trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, 2739dcdaadb6SLluís Vilanova addr, trace_mem_get_info(memop, 1)); 2740*e1dcf352SRichard Henderson 2741*e1dcf352SRichard Henderson if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 2742*e1dcf352SRichard Henderson swap = tcg_temp_new_i32(); 2743*e1dcf352SRichard Henderson switch (memop & MO_SIZE) { 2744*e1dcf352SRichard Henderson case MO_16: 2745*e1dcf352SRichard Henderson tcg_gen_ext16u_i32(swap, val); 2746*e1dcf352SRichard Henderson tcg_gen_bswap16_i32(swap, swap); 2747*e1dcf352SRichard Henderson break; 2748*e1dcf352SRichard Henderson case MO_32: 2749*e1dcf352SRichard Henderson tcg_gen_bswap32_i32(swap, val); 2750*e1dcf352SRichard Henderson break; 2751*e1dcf352SRichard Henderson default: 2752*e1dcf352SRichard Henderson g_assert_not_reached(); 2753*e1dcf352SRichard Henderson } 2754*e1dcf352SRichard Henderson val = swap; 2755*e1dcf352SRichard Henderson memop &= ~MO_BSWAP; 2756*e1dcf352SRichard Henderson } 2757*e1dcf352SRichard Henderson 2758c45cb8bbSRichard Henderson gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx); 2759*e1dcf352SRichard Henderson 2760*e1dcf352SRichard Henderson if (swap) { 2761*e1dcf352SRichard Henderson tcg_temp_free_i32(swap); 2762*e1dcf352SRichard Henderson } 2763951c6300SRichard Henderson } 2764951c6300SRichard Henderson 2765951c6300SRichard Henderson void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop) 2766951c6300SRichard Henderson { 2767*e1dcf352SRichard Henderson TCGMemOp orig_memop; 2768*e1dcf352SRichard Henderson 27693a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) { 2770951c6300SRichard Henderson tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop); 2771951c6300SRichard Henderson if (memop & MO_SIGN) { 2772951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31); 2773951c6300SRichard Henderson } else { 2774951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(val), 0); 2775951c6300SRichard Henderson } 2776951c6300SRichard Henderson return; 2777951c6300SRichard Henderson } 2778951c6300SRichard Henderson 2779*e1dcf352SRichard Henderson tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD); 2780c45cb8bbSRichard Henderson memop = tcg_canonicalize_memop(memop, 1, 0); 27811c2adb95SRichard Henderson trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, 2782dcdaadb6SLluís Vilanova addr, trace_mem_get_info(memop, 0)); 2783*e1dcf352SRichard Henderson 2784*e1dcf352SRichard Henderson orig_memop = memop; 2785*e1dcf352SRichard Henderson if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 2786*e1dcf352SRichard Henderson memop &= ~MO_BSWAP; 2787*e1dcf352SRichard Henderson /* The bswap primitive requires zero-extended input. */ 2788*e1dcf352SRichard Henderson if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) { 2789*e1dcf352SRichard Henderson memop &= ~MO_SIGN; 2790*e1dcf352SRichard Henderson } 2791*e1dcf352SRichard Henderson } 2792*e1dcf352SRichard Henderson 2793c45cb8bbSRichard Henderson gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx); 2794*e1dcf352SRichard Henderson 2795*e1dcf352SRichard Henderson if ((orig_memop ^ memop) & MO_BSWAP) { 2796*e1dcf352SRichard Henderson switch (orig_memop & MO_SIZE) { 2797*e1dcf352SRichard Henderson case MO_16: 2798*e1dcf352SRichard Henderson tcg_gen_bswap16_i64(val, val); 2799*e1dcf352SRichard Henderson if (orig_memop & MO_SIGN) { 2800*e1dcf352SRichard Henderson tcg_gen_ext16s_i64(val, val); 2801*e1dcf352SRichard Henderson } 2802*e1dcf352SRichard Henderson break; 2803*e1dcf352SRichard Henderson case MO_32: 2804*e1dcf352SRichard Henderson tcg_gen_bswap32_i64(val, val); 2805*e1dcf352SRichard Henderson if (orig_memop & MO_SIGN) { 2806*e1dcf352SRichard Henderson tcg_gen_ext32s_i64(val, val); 2807*e1dcf352SRichard Henderson } 2808*e1dcf352SRichard Henderson break; 2809*e1dcf352SRichard Henderson case MO_64: 2810*e1dcf352SRichard Henderson tcg_gen_bswap64_i64(val, val); 2811*e1dcf352SRichard Henderson break; 2812*e1dcf352SRichard Henderson default: 2813*e1dcf352SRichard Henderson g_assert_not_reached(); 2814*e1dcf352SRichard Henderson } 2815*e1dcf352SRichard Henderson } 2816951c6300SRichard Henderson } 2817951c6300SRichard Henderson 2818951c6300SRichard Henderson void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop) 2819951c6300SRichard Henderson { 2820*e1dcf352SRichard Henderson TCGv_i64 swap = NULL; 2821*e1dcf352SRichard Henderson 28223a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) { 2823951c6300SRichard Henderson tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop); 2824951c6300SRichard Henderson return; 2825951c6300SRichard Henderson } 2826951c6300SRichard Henderson 2827*e1dcf352SRichard Henderson tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST); 2828c45cb8bbSRichard Henderson memop = tcg_canonicalize_memop(memop, 1, 1); 28291c2adb95SRichard Henderson trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, 2830dcdaadb6SLluís Vilanova addr, trace_mem_get_info(memop, 1)); 2831*e1dcf352SRichard Henderson 2832*e1dcf352SRichard Henderson if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) { 2833*e1dcf352SRichard Henderson swap = tcg_temp_new_i64(); 2834*e1dcf352SRichard Henderson switch (memop & MO_SIZE) { 2835*e1dcf352SRichard Henderson case MO_16: 2836*e1dcf352SRichard Henderson tcg_gen_ext16u_i64(swap, val); 2837*e1dcf352SRichard Henderson tcg_gen_bswap16_i64(swap, swap); 2838*e1dcf352SRichard Henderson break; 2839*e1dcf352SRichard Henderson case MO_32: 2840*e1dcf352SRichard Henderson tcg_gen_ext32u_i64(swap, val); 2841*e1dcf352SRichard Henderson tcg_gen_bswap32_i64(swap, swap); 2842*e1dcf352SRichard Henderson break; 2843*e1dcf352SRichard Henderson case MO_64: 2844*e1dcf352SRichard Henderson tcg_gen_bswap64_i64(swap, val); 2845*e1dcf352SRichard Henderson break; 2846*e1dcf352SRichard Henderson default: 2847*e1dcf352SRichard Henderson g_assert_not_reached(); 2848*e1dcf352SRichard Henderson } 2849*e1dcf352SRichard Henderson val = swap; 2850*e1dcf352SRichard Henderson memop &= ~MO_BSWAP; 2851*e1dcf352SRichard Henderson } 2852*e1dcf352SRichard Henderson 2853c45cb8bbSRichard Henderson gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx); 2854*e1dcf352SRichard Henderson 2855*e1dcf352SRichard Henderson if (swap) { 2856*e1dcf352SRichard Henderson tcg_temp_free_i64(swap); 2857*e1dcf352SRichard Henderson } 2858951c6300SRichard Henderson } 2859c482cb11SRichard Henderson 2860c482cb11SRichard Henderson static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc) 2861c482cb11SRichard Henderson { 2862c482cb11SRichard Henderson switch (opc & MO_SSIZE) { 2863c482cb11SRichard Henderson case MO_SB: 2864c482cb11SRichard Henderson tcg_gen_ext8s_i32(ret, val); 2865c482cb11SRichard Henderson break; 2866c482cb11SRichard Henderson case MO_UB: 2867c482cb11SRichard Henderson tcg_gen_ext8u_i32(ret, val); 2868c482cb11SRichard Henderson break; 2869c482cb11SRichard Henderson case MO_SW: 2870c482cb11SRichard Henderson tcg_gen_ext16s_i32(ret, val); 2871c482cb11SRichard Henderson break; 2872c482cb11SRichard Henderson case MO_UW: 2873c482cb11SRichard Henderson tcg_gen_ext16u_i32(ret, val); 2874c482cb11SRichard Henderson break; 2875c482cb11SRichard Henderson default: 2876c482cb11SRichard Henderson tcg_gen_mov_i32(ret, val); 2877c482cb11SRichard Henderson break; 2878c482cb11SRichard Henderson } 2879c482cb11SRichard Henderson } 2880c482cb11SRichard Henderson 2881c482cb11SRichard Henderson static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, TCGMemOp opc) 2882c482cb11SRichard Henderson { 2883c482cb11SRichard Henderson switch (opc & MO_SSIZE) { 2884c482cb11SRichard Henderson case MO_SB: 2885c482cb11SRichard Henderson tcg_gen_ext8s_i64(ret, val); 2886c482cb11SRichard Henderson break; 2887c482cb11SRichard Henderson case MO_UB: 2888c482cb11SRichard Henderson tcg_gen_ext8u_i64(ret, val); 2889c482cb11SRichard Henderson break; 2890c482cb11SRichard Henderson case MO_SW: 2891c482cb11SRichard Henderson tcg_gen_ext16s_i64(ret, val); 2892c482cb11SRichard Henderson break; 2893c482cb11SRichard Henderson case MO_UW: 2894c482cb11SRichard Henderson tcg_gen_ext16u_i64(ret, val); 2895c482cb11SRichard Henderson break; 2896c482cb11SRichard Henderson case MO_SL: 2897c482cb11SRichard Henderson tcg_gen_ext32s_i64(ret, val); 2898c482cb11SRichard Henderson break; 2899c482cb11SRichard Henderson case MO_UL: 2900c482cb11SRichard Henderson tcg_gen_ext32u_i64(ret, val); 2901c482cb11SRichard Henderson break; 2902c482cb11SRichard Henderson default: 2903c482cb11SRichard Henderson tcg_gen_mov_i64(ret, val); 2904c482cb11SRichard Henderson break; 2905c482cb11SRichard Henderson } 2906c482cb11SRichard Henderson } 2907c482cb11SRichard Henderson 2908c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU 2909c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, 2910c482cb11SRichard Henderson TCGv_i32, TCGv_i32, TCGv_i32); 2911c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, 2912c482cb11SRichard Henderson TCGv_i64, TCGv_i64, TCGv_i32); 2913c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, 2914c482cb11SRichard Henderson TCGv_i32, TCGv_i32); 2915c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, 2916c482cb11SRichard Henderson TCGv_i64, TCGv_i32); 2917c482cb11SRichard Henderson #else 2918c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32); 2919c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64); 2920c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32); 2921c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64); 2922c482cb11SRichard Henderson #endif 2923c482cb11SRichard Henderson 2924df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64 2925df79b996SRichard Henderson # define WITH_ATOMIC64(X) X, 2926df79b996SRichard Henderson #else 2927df79b996SRichard Henderson # define WITH_ATOMIC64(X) 2928df79b996SRichard Henderson #endif 2929df79b996SRichard Henderson 2930c482cb11SRichard Henderson static void * const table_cmpxchg[16] = { 2931c482cb11SRichard Henderson [MO_8] = gen_helper_atomic_cmpxchgb, 2932c482cb11SRichard Henderson [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le, 2933c482cb11SRichard Henderson [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be, 2934c482cb11SRichard Henderson [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le, 2935c482cb11SRichard Henderson [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be, 2936df79b996SRichard Henderson WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le) 2937df79b996SRichard Henderson WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be) 2938c482cb11SRichard Henderson }; 2939c482cb11SRichard Henderson 2940c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv, 2941c482cb11SRichard Henderson TCGv_i32 newv, TCGArg idx, TCGMemOp memop) 2942c482cb11SRichard Henderson { 2943c482cb11SRichard Henderson memop = tcg_canonicalize_memop(memop, 0, 0); 2944c482cb11SRichard Henderson 2945b1311c4aSEmilio G. Cota if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) { 2946c482cb11SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 2947c482cb11SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 2948c482cb11SRichard Henderson 2949c482cb11SRichard Henderson tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE); 2950c482cb11SRichard Henderson 2951c482cb11SRichard Henderson tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN); 2952c482cb11SRichard Henderson tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1); 2953c482cb11SRichard Henderson tcg_gen_qemu_st_i32(t2, addr, idx, memop); 2954c482cb11SRichard Henderson tcg_temp_free_i32(t2); 2955c482cb11SRichard Henderson 2956c482cb11SRichard Henderson if (memop & MO_SIGN) { 2957c482cb11SRichard Henderson tcg_gen_ext_i32(retv, t1, memop); 2958c482cb11SRichard Henderson } else { 2959c482cb11SRichard Henderson tcg_gen_mov_i32(retv, t1); 2960c482cb11SRichard Henderson } 2961c482cb11SRichard Henderson tcg_temp_free_i32(t1); 2962c482cb11SRichard Henderson } else { 2963c482cb11SRichard Henderson gen_atomic_cx_i32 gen; 2964c482cb11SRichard Henderson 2965c482cb11SRichard Henderson gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)]; 2966c482cb11SRichard Henderson tcg_debug_assert(gen != NULL); 2967c482cb11SRichard Henderson 2968c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU 2969c482cb11SRichard Henderson { 2970c482cb11SRichard Henderson TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx)); 29711c2adb95SRichard Henderson gen(retv, cpu_env, addr, cmpv, newv, oi); 2972c482cb11SRichard Henderson tcg_temp_free_i32(oi); 2973c482cb11SRichard Henderson } 2974c482cb11SRichard Henderson #else 29751c2adb95SRichard Henderson gen(retv, cpu_env, addr, cmpv, newv); 2976c482cb11SRichard Henderson #endif 2977c482cb11SRichard Henderson 2978c482cb11SRichard Henderson if (memop & MO_SIGN) { 2979c482cb11SRichard Henderson tcg_gen_ext_i32(retv, retv, memop); 2980c482cb11SRichard Henderson } 2981c482cb11SRichard Henderson } 2982c482cb11SRichard Henderson } 2983c482cb11SRichard Henderson 2984c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv, 2985c482cb11SRichard Henderson TCGv_i64 newv, TCGArg idx, TCGMemOp memop) 2986c482cb11SRichard Henderson { 2987c482cb11SRichard Henderson memop = tcg_canonicalize_memop(memop, 1, 0); 2988c482cb11SRichard Henderson 2989b1311c4aSEmilio G. Cota if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) { 2990c482cb11SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 2991c482cb11SRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 2992c482cb11SRichard Henderson 2993c482cb11SRichard Henderson tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE); 2994c482cb11SRichard Henderson 2995c482cb11SRichard Henderson tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN); 2996c482cb11SRichard Henderson tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1); 2997c482cb11SRichard Henderson tcg_gen_qemu_st_i64(t2, addr, idx, memop); 2998c482cb11SRichard Henderson tcg_temp_free_i64(t2); 2999c482cb11SRichard Henderson 3000c482cb11SRichard Henderson if (memop & MO_SIGN) { 3001c482cb11SRichard Henderson tcg_gen_ext_i64(retv, t1, memop); 3002c482cb11SRichard Henderson } else { 3003c482cb11SRichard Henderson tcg_gen_mov_i64(retv, t1); 3004c482cb11SRichard Henderson } 3005c482cb11SRichard Henderson tcg_temp_free_i64(t1); 3006c482cb11SRichard Henderson } else if ((memop & MO_SIZE) == MO_64) { 3007df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64 3008c482cb11SRichard Henderson gen_atomic_cx_i64 gen; 3009c482cb11SRichard Henderson 3010c482cb11SRichard Henderson gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)]; 3011c482cb11SRichard Henderson tcg_debug_assert(gen != NULL); 3012c482cb11SRichard Henderson 3013c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU 3014c482cb11SRichard Henderson { 3015c482cb11SRichard Henderson TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx)); 30161c2adb95SRichard Henderson gen(retv, cpu_env, addr, cmpv, newv, oi); 3017c482cb11SRichard Henderson tcg_temp_free_i32(oi); 3018c482cb11SRichard Henderson } 3019c482cb11SRichard Henderson #else 30201c2adb95SRichard Henderson gen(retv, cpu_env, addr, cmpv, newv); 3021c482cb11SRichard Henderson #endif 3022df79b996SRichard Henderson #else 30231c2adb95SRichard Henderson gen_helper_exit_atomic(cpu_env); 302479b1af90SRichard Henderson /* Produce a result, so that we have a well-formed opcode stream 302579b1af90SRichard Henderson with respect to uses of the result in the (dead) code following. */ 302679b1af90SRichard Henderson tcg_gen_movi_i64(retv, 0); 3027df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */ 3028c482cb11SRichard Henderson } else { 3029c482cb11SRichard Henderson TCGv_i32 c32 = tcg_temp_new_i32(); 3030c482cb11SRichard Henderson TCGv_i32 n32 = tcg_temp_new_i32(); 3031c482cb11SRichard Henderson TCGv_i32 r32 = tcg_temp_new_i32(); 3032c482cb11SRichard Henderson 3033c482cb11SRichard Henderson tcg_gen_extrl_i64_i32(c32, cmpv); 3034c482cb11SRichard Henderson tcg_gen_extrl_i64_i32(n32, newv); 3035c482cb11SRichard Henderson tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN); 3036c482cb11SRichard Henderson tcg_temp_free_i32(c32); 3037c482cb11SRichard Henderson tcg_temp_free_i32(n32); 3038c482cb11SRichard Henderson 3039c482cb11SRichard Henderson tcg_gen_extu_i32_i64(retv, r32); 3040c482cb11SRichard Henderson tcg_temp_free_i32(r32); 3041c482cb11SRichard Henderson 3042c482cb11SRichard Henderson if (memop & MO_SIGN) { 3043c482cb11SRichard Henderson tcg_gen_ext_i64(retv, retv, memop); 3044c482cb11SRichard Henderson } 3045c482cb11SRichard Henderson } 3046c482cb11SRichard Henderson } 3047c482cb11SRichard Henderson 3048c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val, 3049c482cb11SRichard Henderson TCGArg idx, TCGMemOp memop, bool new_val, 3050c482cb11SRichard Henderson void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32)) 3051c482cb11SRichard Henderson { 3052c482cb11SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 3053c482cb11SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 3054c482cb11SRichard Henderson 3055c482cb11SRichard Henderson memop = tcg_canonicalize_memop(memop, 0, 0); 3056c482cb11SRichard Henderson 3057c482cb11SRichard Henderson tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN); 3058c482cb11SRichard Henderson gen(t2, t1, val); 3059c482cb11SRichard Henderson tcg_gen_qemu_st_i32(t2, addr, idx, memop); 3060c482cb11SRichard Henderson 3061c482cb11SRichard Henderson tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop); 3062c482cb11SRichard Henderson tcg_temp_free_i32(t1); 3063c482cb11SRichard Henderson tcg_temp_free_i32(t2); 3064c482cb11SRichard Henderson } 3065c482cb11SRichard Henderson 3066c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val, 3067c482cb11SRichard Henderson TCGArg idx, TCGMemOp memop, void * const table[]) 3068c482cb11SRichard Henderson { 3069c482cb11SRichard Henderson gen_atomic_op_i32 gen; 3070c482cb11SRichard Henderson 3071c482cb11SRichard Henderson memop = tcg_canonicalize_memop(memop, 0, 0); 3072c482cb11SRichard Henderson 3073c482cb11SRichard Henderson gen = table[memop & (MO_SIZE | MO_BSWAP)]; 3074c482cb11SRichard Henderson tcg_debug_assert(gen != NULL); 3075c482cb11SRichard Henderson 3076c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU 3077c482cb11SRichard Henderson { 3078c482cb11SRichard Henderson TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx)); 30791c2adb95SRichard Henderson gen(ret, cpu_env, addr, val, oi); 3080c482cb11SRichard Henderson tcg_temp_free_i32(oi); 3081c482cb11SRichard Henderson } 3082c482cb11SRichard Henderson #else 30831c2adb95SRichard Henderson gen(ret, cpu_env, addr, val); 3084c482cb11SRichard Henderson #endif 3085c482cb11SRichard Henderson 3086c482cb11SRichard Henderson if (memop & MO_SIGN) { 3087c482cb11SRichard Henderson tcg_gen_ext_i32(ret, ret, memop); 3088c482cb11SRichard Henderson } 3089c482cb11SRichard Henderson } 3090c482cb11SRichard Henderson 3091c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val, 3092c482cb11SRichard Henderson TCGArg idx, TCGMemOp memop, bool new_val, 3093c482cb11SRichard Henderson void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64)) 3094c482cb11SRichard Henderson { 3095c482cb11SRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3096c482cb11SRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3097c482cb11SRichard Henderson 3098c482cb11SRichard Henderson memop = tcg_canonicalize_memop(memop, 1, 0); 3099c482cb11SRichard Henderson 3100c482cb11SRichard Henderson tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN); 3101c482cb11SRichard Henderson gen(t2, t1, val); 3102c482cb11SRichard Henderson tcg_gen_qemu_st_i64(t2, addr, idx, memop); 3103c482cb11SRichard Henderson 3104c482cb11SRichard Henderson tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop); 3105c482cb11SRichard Henderson tcg_temp_free_i64(t1); 3106c482cb11SRichard Henderson tcg_temp_free_i64(t2); 3107c482cb11SRichard Henderson } 3108c482cb11SRichard Henderson 3109c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val, 3110c482cb11SRichard Henderson TCGArg idx, TCGMemOp memop, void * const table[]) 3111c482cb11SRichard Henderson { 3112c482cb11SRichard Henderson memop = tcg_canonicalize_memop(memop, 1, 0); 3113c482cb11SRichard Henderson 3114c482cb11SRichard Henderson if ((memop & MO_SIZE) == MO_64) { 3115df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64 3116c482cb11SRichard Henderson gen_atomic_op_i64 gen; 3117c482cb11SRichard Henderson 3118c482cb11SRichard Henderson gen = table[memop & (MO_SIZE | MO_BSWAP)]; 3119c482cb11SRichard Henderson tcg_debug_assert(gen != NULL); 3120c482cb11SRichard Henderson 3121c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU 3122c482cb11SRichard Henderson { 3123c482cb11SRichard Henderson TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx)); 31241c2adb95SRichard Henderson gen(ret, cpu_env, addr, val, oi); 3125c482cb11SRichard Henderson tcg_temp_free_i32(oi); 3126c482cb11SRichard Henderson } 3127c482cb11SRichard Henderson #else 31281c2adb95SRichard Henderson gen(ret, cpu_env, addr, val); 3129c482cb11SRichard Henderson #endif 3130df79b996SRichard Henderson #else 31311c2adb95SRichard Henderson gen_helper_exit_atomic(cpu_env); 313279b1af90SRichard Henderson /* Produce a result, so that we have a well-formed opcode stream 313379b1af90SRichard Henderson with respect to uses of the result in the (dead) code following. */ 313479b1af90SRichard Henderson tcg_gen_movi_i64(ret, 0); 3135df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */ 3136c482cb11SRichard Henderson } else { 3137c482cb11SRichard Henderson TCGv_i32 v32 = tcg_temp_new_i32(); 3138c482cb11SRichard Henderson TCGv_i32 r32 = tcg_temp_new_i32(); 3139c482cb11SRichard Henderson 3140c482cb11SRichard Henderson tcg_gen_extrl_i64_i32(v32, val); 3141c482cb11SRichard Henderson do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table); 3142c482cb11SRichard Henderson tcg_temp_free_i32(v32); 3143c482cb11SRichard Henderson 3144c482cb11SRichard Henderson tcg_gen_extu_i32_i64(ret, r32); 3145c482cb11SRichard Henderson tcg_temp_free_i32(r32); 3146c482cb11SRichard Henderson 3147c482cb11SRichard Henderson if (memop & MO_SIGN) { 3148c482cb11SRichard Henderson tcg_gen_ext_i64(ret, ret, memop); 3149c482cb11SRichard Henderson } 3150c482cb11SRichard Henderson } 3151c482cb11SRichard Henderson } 3152c482cb11SRichard Henderson 3153c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW) \ 3154c482cb11SRichard Henderson static void * const table_##NAME[16] = { \ 3155c482cb11SRichard Henderson [MO_8] = gen_helper_atomic_##NAME##b, \ 3156c482cb11SRichard Henderson [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le, \ 3157c482cb11SRichard Henderson [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be, \ 3158c482cb11SRichard Henderson [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le, \ 3159c482cb11SRichard Henderson [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be, \ 3160df79b996SRichard Henderson WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le) \ 3161df79b996SRichard Henderson WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be) \ 3162c482cb11SRichard Henderson }; \ 3163c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32 \ 3164c482cb11SRichard Henderson (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \ 3165c482cb11SRichard Henderson { \ 3166b1311c4aSEmilio G. Cota if (tcg_ctx->tb_cflags & CF_PARALLEL) { \ 3167c482cb11SRichard Henderson do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \ 3168c482cb11SRichard Henderson } else { \ 3169c482cb11SRichard Henderson do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \ 3170c482cb11SRichard Henderson tcg_gen_##OP##_i32); \ 3171c482cb11SRichard Henderson } \ 3172c482cb11SRichard Henderson } \ 3173c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64 \ 3174c482cb11SRichard Henderson (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \ 3175c482cb11SRichard Henderson { \ 3176b1311c4aSEmilio G. Cota if (tcg_ctx->tb_cflags & CF_PARALLEL) { \ 3177c482cb11SRichard Henderson do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \ 3178c482cb11SRichard Henderson } else { \ 3179c482cb11SRichard Henderson do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \ 3180c482cb11SRichard Henderson tcg_gen_##OP##_i64); \ 3181c482cb11SRichard Henderson } \ 3182c482cb11SRichard Henderson } 3183c482cb11SRichard Henderson 3184c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0) 3185c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0) 3186c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0) 3187c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0) 31885507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smin, smin, 0) 31895507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umin, umin, 0) 31905507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smax, smax, 0) 31915507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umax, umax, 0) 3192c482cb11SRichard Henderson 3193c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1) 3194c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1) 3195c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1) 3196c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1) 31975507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smin_fetch, smin, 1) 31985507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umin_fetch, umin, 1) 31995507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smax_fetch, smax, 1) 32005507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umax_fetch, umax, 1) 3201c482cb11SRichard Henderson 3202c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b) 3203c482cb11SRichard Henderson { 3204c482cb11SRichard Henderson tcg_gen_mov_i32(r, b); 3205c482cb11SRichard Henderson } 3206c482cb11SRichard Henderson 3207c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b) 3208c482cb11SRichard Henderson { 3209c482cb11SRichard Henderson tcg_gen_mov_i64(r, b); 3210c482cb11SRichard Henderson } 3211c482cb11SRichard Henderson 3212c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0) 3213c482cb11SRichard Henderson 3214c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER 3215