1951c6300SRichard Henderson /* 2951c6300SRichard Henderson * Tiny Code Generator for QEMU 3951c6300SRichard Henderson * 4951c6300SRichard Henderson * Copyright (c) 2008 Fabrice Bellard 5951c6300SRichard Henderson * 6951c6300SRichard Henderson * Permission is hereby granted, free of charge, to any person obtaining a copy 7951c6300SRichard Henderson * of this software and associated documentation files (the "Software"), to deal 8951c6300SRichard Henderson * in the Software without restriction, including without limitation the rights 9951c6300SRichard Henderson * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10951c6300SRichard Henderson * copies of the Software, and to permit persons to whom the Software is 11951c6300SRichard Henderson * furnished to do so, subject to the following conditions: 12951c6300SRichard Henderson * 13951c6300SRichard Henderson * The above copyright notice and this permission notice shall be included in 14951c6300SRichard Henderson * all copies or substantial portions of the Software. 15951c6300SRichard Henderson * 16951c6300SRichard Henderson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17951c6300SRichard Henderson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18951c6300SRichard Henderson * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19951c6300SRichard Henderson * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20951c6300SRichard Henderson * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21951c6300SRichard Henderson * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22951c6300SRichard Henderson * THE SOFTWARE. 23951c6300SRichard Henderson */ 24951c6300SRichard Henderson 25757e725bSPeter Maydell #include "qemu/osdep.h" 26dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h" 2747f7313dSRichard Henderson #include "tcg/tcg-temp-internal.h" 28ad3d0e4dSRichard Henderson #include "tcg/tcg-op-common.h" 29cac9b0fdSRichard Henderson #include "exec/translation-block.h" 30e6d86bedSEmilio G. Cota #include "exec/plugin-gen.h" 31d56fea79SRichard Henderson #include "tcg-internal.h" 32951c6300SRichard Henderson 33951c6300SRichard Henderson 34ecfa1877SRichard Henderson /* 35ecfa1877SRichard Henderson * Encourage the compiler to tail-call to a function, rather than inlining. 36ecfa1877SRichard Henderson * Minimizes code size across 99 bottles of beer on the wall. 37ecfa1877SRichard Henderson */ 38ecfa1877SRichard Henderson #define NI __attribute__((noinline)) 39ecfa1877SRichard Henderson 40ecfa1877SRichard Henderson void NI tcg_gen_op1(TCGOpcode opc, TCGArg a1) 41951c6300SRichard Henderson { 42d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 1); 4375e8b9b7SRichard Henderson op->args[0] = a1; 44951c6300SRichard Henderson } 45951c6300SRichard Henderson 46ecfa1877SRichard Henderson void NI tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2) 47951c6300SRichard Henderson { 48d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 2); 4975e8b9b7SRichard Henderson op->args[0] = a1; 5075e8b9b7SRichard Henderson op->args[1] = a2; 51951c6300SRichard Henderson } 52951c6300SRichard Henderson 53ecfa1877SRichard Henderson void NI tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3) 54951c6300SRichard Henderson { 55d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 3); 5675e8b9b7SRichard Henderson op->args[0] = a1; 5775e8b9b7SRichard Henderson op->args[1] = a2; 5875e8b9b7SRichard Henderson op->args[2] = a3; 59951c6300SRichard Henderson } 60951c6300SRichard Henderson 61ecfa1877SRichard Henderson void NI tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4) 62951c6300SRichard Henderson { 63d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 4); 6475e8b9b7SRichard Henderson op->args[0] = a1; 6575e8b9b7SRichard Henderson op->args[1] = a2; 6675e8b9b7SRichard Henderson op->args[2] = a3; 6775e8b9b7SRichard Henderson op->args[3] = a4; 68951c6300SRichard Henderson } 69951c6300SRichard Henderson 70ecfa1877SRichard Henderson void NI tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 71b7e8b17aSRichard Henderson TCGArg a4, TCGArg a5) 72951c6300SRichard Henderson { 73d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 5); 7475e8b9b7SRichard Henderson op->args[0] = a1; 7575e8b9b7SRichard Henderson op->args[1] = a2; 7675e8b9b7SRichard Henderson op->args[2] = a3; 7775e8b9b7SRichard Henderson op->args[3] = a4; 7875e8b9b7SRichard Henderson op->args[4] = a5; 79951c6300SRichard Henderson } 80951c6300SRichard Henderson 81ecfa1877SRichard Henderson void NI tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, 82b7e8b17aSRichard Henderson TCGArg a4, TCGArg a5, TCGArg a6) 83951c6300SRichard Henderson { 84d4478943SPhilippe Mathieu-Daudé TCGOp *op = tcg_emit_op(opc, 6); 8575e8b9b7SRichard Henderson op->args[0] = a1; 8675e8b9b7SRichard Henderson op->args[1] = a2; 8775e8b9b7SRichard Henderson op->args[2] = a3; 8875e8b9b7SRichard Henderson op->args[3] = a4; 8975e8b9b7SRichard Henderson op->args[4] = a5; 9075e8b9b7SRichard Henderson op->args[5] = a6; 91951c6300SRichard Henderson } 92951c6300SRichard Henderson 936fc75d50SRichard Henderson /* 946fc75d50SRichard Henderson * With CONFIG_DEBUG_TCG, tcgv_*_tmp via tcgv_*_arg, is an out-of-line 956fc75d50SRichard Henderson * assertion check. Force tail calls to avoid too much code expansion. 966fc75d50SRichard Henderson */ 976fc75d50SRichard Henderson #ifdef CONFIG_DEBUG_TCG 986fc75d50SRichard Henderson # define DNI NI 996fc75d50SRichard Henderson #else 1006fc75d50SRichard Henderson # define DNI 1016fc75d50SRichard Henderson #endif 1026fc75d50SRichard Henderson 10317b9fadbSRichard Henderson static void DNI tcg_gen_op1_i32(TCGOpcode opc, TCGv_i32 a1) 1046fc75d50SRichard Henderson { 1056fc75d50SRichard Henderson tcg_gen_op1(opc, tcgv_i32_arg(a1)); 1066fc75d50SRichard Henderson } 1076fc75d50SRichard Henderson 10817b9fadbSRichard Henderson static void DNI tcg_gen_op1_i64(TCGOpcode opc, TCGv_i64 a1) 1096fc75d50SRichard Henderson { 1106fc75d50SRichard Henderson tcg_gen_op1(opc, tcgv_i64_arg(a1)); 1116fc75d50SRichard Henderson } 1126fc75d50SRichard Henderson 11317b9fadbSRichard Henderson static void DNI tcg_gen_op1i(TCGOpcode opc, TCGArg a1) 1146fc75d50SRichard Henderson { 1156fc75d50SRichard Henderson tcg_gen_op1(opc, a1); 1166fc75d50SRichard Henderson } 1176fc75d50SRichard Henderson 11817b9fadbSRichard Henderson static void DNI tcg_gen_op2_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2) 1196fc75d50SRichard Henderson { 1206fc75d50SRichard Henderson tcg_gen_op2(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2)); 1216fc75d50SRichard Henderson } 1226fc75d50SRichard Henderson 12317b9fadbSRichard Henderson static void DNI tcg_gen_op2_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2) 1246fc75d50SRichard Henderson { 1256fc75d50SRichard Henderson tcg_gen_op2(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2)); 1266fc75d50SRichard Henderson } 1276fc75d50SRichard Henderson 12817b9fadbSRichard Henderson static void DNI tcg_gen_op3_i32(TCGOpcode opc, TCGv_i32 a1, 12917b9fadbSRichard Henderson TCGv_i32 a2, TCGv_i32 a3) 1306fc75d50SRichard Henderson { 1316fc75d50SRichard Henderson tcg_gen_op3(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3)); 1326fc75d50SRichard Henderson } 1336fc75d50SRichard Henderson 13417b9fadbSRichard Henderson static void DNI tcg_gen_op3_i64(TCGOpcode opc, TCGv_i64 a1, 13517b9fadbSRichard Henderson TCGv_i64 a2, TCGv_i64 a3) 1366fc75d50SRichard Henderson { 1376fc75d50SRichard Henderson tcg_gen_op3(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3)); 1386fc75d50SRichard Henderson } 1396fc75d50SRichard Henderson 14017b9fadbSRichard Henderson static void DNI tcg_gen_op3i_i32(TCGOpcode opc, TCGv_i32 a1, 14117b9fadbSRichard Henderson TCGv_i32 a2, TCGArg a3) 1426fc75d50SRichard Henderson { 1436fc75d50SRichard Henderson tcg_gen_op3(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3); 1446fc75d50SRichard Henderson } 1456fc75d50SRichard Henderson 14617b9fadbSRichard Henderson static void DNI tcg_gen_op3i_i64(TCGOpcode opc, TCGv_i64 a1, 14717b9fadbSRichard Henderson TCGv_i64 a2, TCGArg a3) 1486fc75d50SRichard Henderson { 1496fc75d50SRichard Henderson tcg_gen_op3(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3); 1506fc75d50SRichard Henderson } 1516fc75d50SRichard Henderson 15217b9fadbSRichard Henderson static void DNI tcg_gen_ldst_op_i32(TCGOpcode opc, TCGv_i32 val, 1536fc75d50SRichard Henderson TCGv_ptr base, TCGArg offset) 1546fc75d50SRichard Henderson { 1556fc75d50SRichard Henderson tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_ptr_arg(base), offset); 1566fc75d50SRichard Henderson } 1576fc75d50SRichard Henderson 15817b9fadbSRichard Henderson static void DNI tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val, 1596fc75d50SRichard Henderson TCGv_ptr base, TCGArg offset) 1606fc75d50SRichard Henderson { 1616fc75d50SRichard Henderson tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_ptr_arg(base), offset); 1626fc75d50SRichard Henderson } 1636fc75d50SRichard Henderson 16417b9fadbSRichard Henderson static void DNI tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 1656fc75d50SRichard Henderson TCGv_i32 a3, TCGv_i32 a4) 1666fc75d50SRichard Henderson { 1676fc75d50SRichard Henderson tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 1686fc75d50SRichard Henderson tcgv_i32_arg(a3), tcgv_i32_arg(a4)); 1696fc75d50SRichard Henderson } 1706fc75d50SRichard Henderson 17117b9fadbSRichard Henderson static void DNI tcg_gen_op4_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 1726fc75d50SRichard Henderson TCGv_i64 a3, TCGv_i64 a4) 1736fc75d50SRichard Henderson { 1746fc75d50SRichard Henderson tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), 1756fc75d50SRichard Henderson tcgv_i64_arg(a3), tcgv_i64_arg(a4)); 1766fc75d50SRichard Henderson } 1776fc75d50SRichard Henderson 17817b9fadbSRichard Henderson static void DNI tcg_gen_op4i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 1796fc75d50SRichard Henderson TCGv_i32 a3, TCGArg a4) 1806fc75d50SRichard Henderson { 1816fc75d50SRichard Henderson tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 1826fc75d50SRichard Henderson tcgv_i32_arg(a3), a4); 1836fc75d50SRichard Henderson } 1846fc75d50SRichard Henderson 18517b9fadbSRichard Henderson static void DNI tcg_gen_op4i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 1866fc75d50SRichard Henderson TCGv_i64 a3, TCGArg a4) 1876fc75d50SRichard Henderson { 1886fc75d50SRichard Henderson tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), 1896fc75d50SRichard Henderson tcgv_i64_arg(a3), a4); 1906fc75d50SRichard Henderson } 1916fc75d50SRichard Henderson 19217b9fadbSRichard Henderson static void DNI tcg_gen_op4ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 1936fc75d50SRichard Henderson TCGArg a3, TCGArg a4) 1946fc75d50SRichard Henderson { 1956fc75d50SRichard Henderson tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3, a4); 1966fc75d50SRichard Henderson } 1976fc75d50SRichard Henderson 19817b9fadbSRichard Henderson static void DNI tcg_gen_op4ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 1996fc75d50SRichard Henderson TCGArg a3, TCGArg a4) 2006fc75d50SRichard Henderson { 2016fc75d50SRichard Henderson tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3, a4); 2026fc75d50SRichard Henderson } 2036fc75d50SRichard Henderson 20417b9fadbSRichard Henderson static void DNI tcg_gen_op5_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 2056fc75d50SRichard Henderson TCGv_i32 a3, TCGv_i32 a4, TCGv_i32 a5) 2066fc75d50SRichard Henderson { 2076fc75d50SRichard Henderson tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 2086fc75d50SRichard Henderson tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5)); 2096fc75d50SRichard Henderson } 2106fc75d50SRichard Henderson 21117b9fadbSRichard Henderson static void DNI tcg_gen_op5_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 2126fc75d50SRichard Henderson TCGv_i64 a3, TCGv_i64 a4, TCGv_i64 a5) 2136fc75d50SRichard Henderson { 2146fc75d50SRichard Henderson tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), 2156fc75d50SRichard Henderson tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5)); 2166fc75d50SRichard Henderson } 2176fc75d50SRichard Henderson 21817b9fadbSRichard Henderson static void DNI tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 2196fc75d50SRichard Henderson TCGv_i32 a3, TCGArg a4, TCGArg a5) 2206fc75d50SRichard Henderson { 2216fc75d50SRichard Henderson tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 2226fc75d50SRichard Henderson tcgv_i32_arg(a3), a4, a5); 2236fc75d50SRichard Henderson } 2246fc75d50SRichard Henderson 22517b9fadbSRichard Henderson static void DNI tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 2266fc75d50SRichard Henderson TCGv_i64 a3, TCGArg a4, TCGArg a5) 2276fc75d50SRichard Henderson { 2286fc75d50SRichard Henderson tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), 2296fc75d50SRichard Henderson tcgv_i64_arg(a3), a4, a5); 2306fc75d50SRichard Henderson } 2316fc75d50SRichard Henderson 23217b9fadbSRichard Henderson static void DNI tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 23317b9fadbSRichard Henderson TCGv_i32 a3, TCGv_i32 a4, 23417b9fadbSRichard Henderson TCGv_i32 a5, TCGv_i32 a6) 2356fc75d50SRichard Henderson { 2366fc75d50SRichard Henderson tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 2376fc75d50SRichard Henderson tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5), 2386fc75d50SRichard Henderson tcgv_i32_arg(a6)); 2396fc75d50SRichard Henderson } 2406fc75d50SRichard Henderson 24117b9fadbSRichard Henderson static void DNI tcg_gen_op6_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 24217b9fadbSRichard Henderson TCGv_i64 a3, TCGv_i64 a4, 24317b9fadbSRichard Henderson TCGv_i64 a5, TCGv_i64 a6) 2446fc75d50SRichard Henderson { 2456fc75d50SRichard Henderson tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), 2466fc75d50SRichard Henderson tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5), 2476fc75d50SRichard Henderson tcgv_i64_arg(a6)); 2486fc75d50SRichard Henderson } 2496fc75d50SRichard Henderson 25017b9fadbSRichard Henderson static void DNI tcg_gen_op6i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 25117b9fadbSRichard Henderson TCGv_i32 a3, TCGv_i32 a4, 25217b9fadbSRichard Henderson TCGv_i32 a5, TCGArg a6) 2536fc75d50SRichard Henderson { 2546fc75d50SRichard Henderson tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 2556fc75d50SRichard Henderson tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5), a6); 2566fc75d50SRichard Henderson } 2576fc75d50SRichard Henderson 25817b9fadbSRichard Henderson static void DNI tcg_gen_op6i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, 25917b9fadbSRichard Henderson TCGv_i64 a3, TCGv_i64 a4, 26017b9fadbSRichard Henderson TCGv_i64 a5, TCGArg a6) 2616fc75d50SRichard Henderson { 2626fc75d50SRichard Henderson tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), 2636fc75d50SRichard Henderson tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5), a6); 2646fc75d50SRichard Henderson } 2656fc75d50SRichard Henderson 26617b9fadbSRichard Henderson static void DNI tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, 26717b9fadbSRichard Henderson TCGv_i32 a3, TCGv_i32 a4, 26817b9fadbSRichard Henderson TCGArg a5, TCGArg a6) 2696fc75d50SRichard Henderson { 2706fc75d50SRichard Henderson tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), 2716fc75d50SRichard Henderson tcgv_i32_arg(a3), tcgv_i32_arg(a4), a5, a6); 2726fc75d50SRichard Henderson } 2736fc75d50SRichard Henderson 274f85b1fc4SRichard Henderson /* Generic ops. */ 275f85b1fc4SRichard Henderson 27601bbb6e3SRichard Henderson void gen_set_label(TCGLabel *l) 27701bbb6e3SRichard Henderson { 27801bbb6e3SRichard Henderson l->present = 1; 27901bbb6e3SRichard Henderson tcg_gen_op1(INDEX_op_set_label, label_arg(l)); 28001bbb6e3SRichard Henderson } 28101bbb6e3SRichard Henderson 282f85b1fc4SRichard Henderson static void add_last_as_label_use(TCGLabel *l) 283f85b1fc4SRichard Henderson { 284f85b1fc4SRichard Henderson TCGLabelUse *u = tcg_malloc(sizeof(TCGLabelUse)); 285f85b1fc4SRichard Henderson 286f85b1fc4SRichard Henderson u->op = tcg_last_op(); 287f85b1fc4SRichard Henderson QSIMPLEQ_INSERT_TAIL(&l->branches, u, next); 288f85b1fc4SRichard Henderson } 289f85b1fc4SRichard Henderson 290f85b1fc4SRichard Henderson void tcg_gen_br(TCGLabel *l) 291f85b1fc4SRichard Henderson { 292f85b1fc4SRichard Henderson tcg_gen_op1(INDEX_op_br, label_arg(l)); 293f85b1fc4SRichard Henderson add_last_as_label_use(l); 294f85b1fc4SRichard Henderson } 295f85b1fc4SRichard Henderson 296f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type) 297f65e19bcSPranith Kumar { 298c914d46dSRichard Henderson #ifdef CONFIG_USER_ONLY 299c914d46dSRichard Henderson bool parallel = tcg_ctx->gen_tb->cflags & CF_PARALLEL; 300c914d46dSRichard Henderson #else 301c914d46dSRichard Henderson /* 302c914d46dSRichard Henderson * It is tempting to elide the barrier in a uniprocessor context. 303c914d46dSRichard Henderson * However, even with a single cpu we have i/o threads running in 304c914d46dSRichard Henderson * parallel, and lack of memory order can result in e.g. virtio 305c914d46dSRichard Henderson * queue entries being read incorrectly. 306c914d46dSRichard Henderson */ 307c914d46dSRichard Henderson bool parallel = true; 308c914d46dSRichard Henderson #endif 309c914d46dSRichard Henderson 310c914d46dSRichard Henderson if (parallel) { 311b7e8b17aSRichard Henderson tcg_gen_op1(INDEX_op_mb, mb_type); 312f65e19bcSPranith Kumar } 313f65e19bcSPranith Kumar } 314f65e19bcSPranith Kumar 31501bbb6e3SRichard Henderson void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr) 31601bbb6e3SRichard Henderson { 31701bbb6e3SRichard Henderson tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr); 31801bbb6e3SRichard Henderson } 31901bbb6e3SRichard Henderson 32001bbb6e3SRichard Henderson void tcg_gen_plugin_cb_end(void) 32101bbb6e3SRichard Henderson { 32201bbb6e3SRichard Henderson tcg_emit_op(INDEX_op_plugin_cb_end, 0); 32301bbb6e3SRichard Henderson } 32401bbb6e3SRichard Henderson 325951c6300SRichard Henderson /* 32 bit ops */ 326951c6300SRichard Henderson 32709607d35SRichard Henderson void tcg_gen_discard_i32(TCGv_i32 arg) 32809607d35SRichard Henderson { 32909607d35SRichard Henderson tcg_gen_op1_i32(INDEX_op_discard, arg); 33009607d35SRichard Henderson } 33109607d35SRichard Henderson 33209607d35SRichard Henderson void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 arg) 33309607d35SRichard Henderson { 33409607d35SRichard Henderson if (ret != arg) { 33509607d35SRichard Henderson tcg_gen_op2_i32(INDEX_op_mov_i32, ret, arg); 33609607d35SRichard Henderson } 33709607d35SRichard Henderson } 33809607d35SRichard Henderson 33911d11d61SRichard Henderson void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg) 34011d11d61SRichard Henderson { 34111d11d61SRichard Henderson tcg_gen_mov_i32(ret, tcg_constant_i32(arg)); 34211d11d61SRichard Henderson } 34311d11d61SRichard Henderson 34409607d35SRichard Henderson void tcg_gen_add_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 34509607d35SRichard Henderson { 34609607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_add_i32, ret, arg1, arg2); 34709607d35SRichard Henderson } 34809607d35SRichard Henderson 349951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 350951c6300SRichard Henderson { 351951c6300SRichard Henderson /* some cases can be optimized here */ 352951c6300SRichard Henderson if (arg2 == 0) { 353951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 354951c6300SRichard Henderson } else { 35511d11d61SRichard Henderson tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2)); 356951c6300SRichard Henderson } 357951c6300SRichard Henderson } 358951c6300SRichard Henderson 35909607d35SRichard Henderson void tcg_gen_sub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 36009607d35SRichard Henderson { 36109607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_sub_i32, ret, arg1, arg2); 36209607d35SRichard Henderson } 36309607d35SRichard Henderson 364951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2) 365951c6300SRichard Henderson { 366*b701f195SRichard Henderson if (arg1 == 0) { 367*b701f195SRichard Henderson tcg_gen_neg_i32(ret, arg2); 368951c6300SRichard Henderson } else { 36911d11d61SRichard Henderson tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2); 370951c6300SRichard Henderson } 371951c6300SRichard Henderson } 372951c6300SRichard Henderson 373951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 374951c6300SRichard Henderson { 375951c6300SRichard Henderson /* some cases can be optimized here */ 376951c6300SRichard Henderson if (arg2 == 0) { 377951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 378951c6300SRichard Henderson } else { 37911d11d61SRichard Henderson tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2)); 380951c6300SRichard Henderson } 381951c6300SRichard Henderson } 382951c6300SRichard Henderson 38309607d35SRichard Henderson void tcg_gen_neg_i32(TCGv_i32 ret, TCGv_i32 arg) 38409607d35SRichard Henderson { 38509607d35SRichard Henderson tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg); 38609607d35SRichard Henderson } 38709607d35SRichard Henderson 38809607d35SRichard Henderson void tcg_gen_and_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 38909607d35SRichard Henderson { 39009607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_and_i32, ret, arg1, arg2); 39109607d35SRichard Henderson } 39209607d35SRichard Henderson 393474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 394951c6300SRichard Henderson { 395951c6300SRichard Henderson /* Some cases can be optimized here. */ 396951c6300SRichard Henderson switch (arg2) { 397951c6300SRichard Henderson case 0: 398951c6300SRichard Henderson tcg_gen_movi_i32(ret, 0); 399951c6300SRichard Henderson return; 400474b2e8fSRichard Henderson case -1: 401951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 402951c6300SRichard Henderson return; 403474b2e8fSRichard Henderson case 0xff: 404951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i32. */ 405951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 406951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1); 407951c6300SRichard Henderson return; 408951c6300SRichard Henderson } 409951c6300SRichard Henderson break; 410474b2e8fSRichard Henderson case 0xffff: 411951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 412951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1); 413951c6300SRichard Henderson return; 414951c6300SRichard Henderson } 415951c6300SRichard Henderson break; 416951c6300SRichard Henderson } 41711d11d61SRichard Henderson 41811d11d61SRichard Henderson tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2)); 419951c6300SRichard Henderson } 420951c6300SRichard Henderson 42109607d35SRichard Henderson void tcg_gen_or_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 42209607d35SRichard Henderson { 42309607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_or_i32, ret, arg1, arg2); 42409607d35SRichard Henderson } 42509607d35SRichard Henderson 426951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 427951c6300SRichard Henderson { 428951c6300SRichard Henderson /* Some cases can be optimized here. */ 429951c6300SRichard Henderson if (arg2 == -1) { 430951c6300SRichard Henderson tcg_gen_movi_i32(ret, -1); 431951c6300SRichard Henderson } else if (arg2 == 0) { 432951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 433951c6300SRichard Henderson } else { 43411d11d61SRichard Henderson tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2)); 435951c6300SRichard Henderson } 436951c6300SRichard Henderson } 437951c6300SRichard Henderson 43809607d35SRichard Henderson void tcg_gen_xor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 43909607d35SRichard Henderson { 44009607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_xor_i32, ret, arg1, arg2); 44109607d35SRichard Henderson } 44209607d35SRichard Henderson 443951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 444951c6300SRichard Henderson { 445951c6300SRichard Henderson /* Some cases can be optimized here. */ 446951c6300SRichard Henderson if (arg2 == 0) { 447951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 448951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) { 449951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i32. */ 450951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1); 451951c6300SRichard Henderson } else { 45211d11d61SRichard Henderson tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2)); 453951c6300SRichard Henderson } 454951c6300SRichard Henderson } 455951c6300SRichard Henderson 45609607d35SRichard Henderson void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 arg) 45709607d35SRichard Henderson { 45809607d35SRichard Henderson if (TCG_TARGET_HAS_not_i32) { 45909607d35SRichard Henderson tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg); 46009607d35SRichard Henderson } else { 46109607d35SRichard Henderson tcg_gen_xori_i32(ret, arg, -1); 46209607d35SRichard Henderson } 46309607d35SRichard Henderson } 46409607d35SRichard Henderson 46509607d35SRichard Henderson void tcg_gen_shl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 46609607d35SRichard Henderson { 46709607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_shl_i32, ret, arg1, arg2); 46809607d35SRichard Henderson } 46909607d35SRichard Henderson 470474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 471951c6300SRichard Henderson { 472474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 473951c6300SRichard Henderson if (arg2 == 0) { 474951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 475951c6300SRichard Henderson } else { 47611d11d61SRichard Henderson tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2)); 477951c6300SRichard Henderson } 478951c6300SRichard Henderson } 479951c6300SRichard Henderson 48009607d35SRichard Henderson void tcg_gen_shr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 48109607d35SRichard Henderson { 48209607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_shr_i32, ret, arg1, arg2); 48309607d35SRichard Henderson } 48409607d35SRichard Henderson 485474b2e8fSRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 486951c6300SRichard Henderson { 487474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 488951c6300SRichard Henderson if (arg2 == 0) { 489951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 490951c6300SRichard Henderson } else { 49111d11d61SRichard Henderson tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2)); 492951c6300SRichard Henderson } 493951c6300SRichard Henderson } 494951c6300SRichard Henderson 49509607d35SRichard Henderson void tcg_gen_sar_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 49609607d35SRichard Henderson { 49709607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_sar_i32, ret, arg1, arg2); 49809607d35SRichard Henderson } 49909607d35SRichard Henderson 500474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 501951c6300SRichard Henderson { 502474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 503951c6300SRichard Henderson if (arg2 == 0) { 504951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 505951c6300SRichard Henderson } else { 50611d11d61SRichard Henderson tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2)); 507951c6300SRichard Henderson } 508951c6300SRichard Henderson } 509951c6300SRichard Henderson 51042a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l) 511951c6300SRichard Henderson { 512951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 51342a268c2SRichard Henderson tcg_gen_br(l); 514951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 51542a268c2SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l)); 516f85b1fc4SRichard Henderson add_last_as_label_use(l); 517951c6300SRichard Henderson } 518951c6300SRichard Henderson } 519951c6300SRichard Henderson 52042a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l) 521951c6300SRichard Henderson { 52237ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 52337ed3bf1SRichard Henderson tcg_gen_br(l); 52437ed3bf1SRichard Henderson } else if (cond != TCG_COND_NEVER) { 52511d11d61SRichard Henderson tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l); 526951c6300SRichard Henderson } 52737ed3bf1SRichard Henderson } 528951c6300SRichard Henderson 529951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret, 530951c6300SRichard Henderson TCGv_i32 arg1, TCGv_i32 arg2) 531951c6300SRichard Henderson { 532951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 533951c6300SRichard Henderson tcg_gen_movi_i32(ret, 1); 534951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 535951c6300SRichard Henderson tcg_gen_movi_i32(ret, 0); 536951c6300SRichard Henderson } else { 537951c6300SRichard Henderson tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); 538951c6300SRichard Henderson } 539951c6300SRichard Henderson } 540951c6300SRichard Henderson 541951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, 542951c6300SRichard Henderson TCGv_i32 arg1, int32_t arg2) 543951c6300SRichard Henderson { 54411d11d61SRichard Henderson tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2)); 545951c6300SRichard Henderson } 546951c6300SRichard Henderson 5473635502dSRichard Henderson void tcg_gen_negsetcond_i32(TCGCond cond, TCGv_i32 ret, 5483635502dSRichard Henderson TCGv_i32 arg1, TCGv_i32 arg2) 5493635502dSRichard Henderson { 5503635502dSRichard Henderson if (cond == TCG_COND_ALWAYS) { 5513635502dSRichard Henderson tcg_gen_movi_i32(ret, -1); 5523635502dSRichard Henderson } else if (cond == TCG_COND_NEVER) { 5533635502dSRichard Henderson tcg_gen_movi_i32(ret, 0); 5543635502dSRichard Henderson } else if (TCG_TARGET_HAS_negsetcond_i32) { 5553635502dSRichard Henderson tcg_gen_op4i_i32(INDEX_op_negsetcond_i32, ret, arg1, arg2, cond); 5563635502dSRichard Henderson } else { 5573635502dSRichard Henderson tcg_gen_setcond_i32(cond, ret, arg1, arg2); 5583635502dSRichard Henderson tcg_gen_neg_i32(ret, ret); 5593635502dSRichard Henderson } 5603635502dSRichard Henderson } 5613635502dSRichard Henderson 56293c86ecdSPaolo Bonzini void tcg_gen_negsetcondi_i32(TCGCond cond, TCGv_i32 ret, 56393c86ecdSPaolo Bonzini TCGv_i32 arg1, int32_t arg2) 56493c86ecdSPaolo Bonzini { 56593c86ecdSPaolo Bonzini tcg_gen_negsetcond_i32(cond, ret, arg1, tcg_constant_i32(arg2)); 56693c86ecdSPaolo Bonzini } 56793c86ecdSPaolo Bonzini 56809607d35SRichard Henderson void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 56909607d35SRichard Henderson { 57009607d35SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, ret, arg1, arg2); 57109607d35SRichard Henderson } 57209607d35SRichard Henderson 573951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 574951c6300SRichard Henderson { 575b2e3ae94SRichard Henderson if (arg2 == 0) { 576b2e3ae94SRichard Henderson tcg_gen_movi_i32(ret, 0); 577b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 578b2e3ae94SRichard Henderson tcg_gen_shli_i32(ret, arg1, ctz32(arg2)); 579b2e3ae94SRichard Henderson } else { 58011d11d61SRichard Henderson tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2)); 581951c6300SRichard Henderson } 582b2e3ae94SRichard Henderson } 583951c6300SRichard Henderson 584951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 585951c6300SRichard Henderson { 586951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 587951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2); 588951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 5895dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 590951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 591951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2); 592951c6300SRichard Henderson tcg_temp_free_i32(t0); 593951c6300SRichard Henderson } else { 594951c6300SRichard Henderson gen_helper_div_i32(ret, arg1, arg2); 595951c6300SRichard Henderson } 596951c6300SRichard Henderson } 597951c6300SRichard Henderson 598951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 599951c6300SRichard Henderson { 600951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 601951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2); 602951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 6035dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 604951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2); 605951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 606951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 607951c6300SRichard Henderson tcg_temp_free_i32(t0); 608951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 6095dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 610951c6300SRichard Henderson tcg_gen_sari_i32(t0, arg1, 31); 611951c6300SRichard Henderson tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2); 612951c6300SRichard Henderson tcg_temp_free_i32(t0); 613951c6300SRichard Henderson } else { 614951c6300SRichard Henderson gen_helper_rem_i32(ret, arg1, arg2); 615951c6300SRichard Henderson } 616951c6300SRichard Henderson } 617951c6300SRichard Henderson 618951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 619951c6300SRichard Henderson { 620951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i32) { 621951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2); 622951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 6235dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 624bfefdbeaSRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 625bfefdbeaSRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, zero, arg2); 626951c6300SRichard Henderson tcg_temp_free_i32(t0); 627951c6300SRichard Henderson } else { 628951c6300SRichard Henderson gen_helper_divu_i32(ret, arg1, arg2); 629951c6300SRichard Henderson } 630951c6300SRichard Henderson } 631951c6300SRichard Henderson 632951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 633951c6300SRichard Henderson { 634951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i32) { 635951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); 636951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i32) { 6375dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 638951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2); 639951c6300SRichard Henderson tcg_gen_mul_i32(t0, t0, arg2); 640951c6300SRichard Henderson tcg_gen_sub_i32(ret, arg1, t0); 641951c6300SRichard Henderson tcg_temp_free_i32(t0); 642951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i32) { 6435dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 644bfefdbeaSRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 645bfefdbeaSRichard Henderson tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, zero, arg2); 646951c6300SRichard Henderson tcg_temp_free_i32(t0); 647951c6300SRichard Henderson } else { 648951c6300SRichard Henderson gen_helper_remu_i32(ret, arg1, arg2); 649951c6300SRichard Henderson } 650951c6300SRichard Henderson } 651951c6300SRichard Henderson 652951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 653951c6300SRichard Henderson { 654951c6300SRichard Henderson if (TCG_TARGET_HAS_andc_i32) { 655951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2); 656951c6300SRichard Henderson } else { 6575dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 658951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 659951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, t0); 660951c6300SRichard Henderson tcg_temp_free_i32(t0); 661951c6300SRichard Henderson } 662951c6300SRichard Henderson } 663951c6300SRichard Henderson 664951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 665951c6300SRichard Henderson { 666951c6300SRichard Henderson if (TCG_TARGET_HAS_eqv_i32) { 667951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2); 668951c6300SRichard Henderson } else { 669951c6300SRichard Henderson tcg_gen_xor_i32(ret, arg1, arg2); 670951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 671951c6300SRichard Henderson } 672951c6300SRichard Henderson } 673951c6300SRichard Henderson 674951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 675951c6300SRichard Henderson { 676951c6300SRichard Henderson if (TCG_TARGET_HAS_nand_i32) { 677951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2); 678951c6300SRichard Henderson } else { 679951c6300SRichard Henderson tcg_gen_and_i32(ret, arg1, arg2); 680951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 681951c6300SRichard Henderson } 682951c6300SRichard Henderson } 683951c6300SRichard Henderson 684951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 685951c6300SRichard Henderson { 686951c6300SRichard Henderson if (TCG_TARGET_HAS_nor_i32) { 687951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2); 688951c6300SRichard Henderson } else { 689951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, arg2); 690951c6300SRichard Henderson tcg_gen_not_i32(ret, ret); 691951c6300SRichard Henderson } 692951c6300SRichard Henderson } 693951c6300SRichard Henderson 694951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 695951c6300SRichard Henderson { 696951c6300SRichard Henderson if (TCG_TARGET_HAS_orc_i32) { 697951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2); 698951c6300SRichard Henderson } else { 6995dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 700951c6300SRichard Henderson tcg_gen_not_i32(t0, arg2); 701951c6300SRichard Henderson tcg_gen_or_i32(ret, arg1, t0); 702951c6300SRichard Henderson tcg_temp_free_i32(t0); 703951c6300SRichard Henderson } 704951c6300SRichard Henderson } 705951c6300SRichard Henderson 7060e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 7070e28d006SRichard Henderson { 7080e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 7090e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2); 7100e28d006SRichard Henderson } else if (TCG_TARGET_HAS_clz_i64) { 7115dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 7125dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 7130e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 7140e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 7150e28d006SRichard Henderson tcg_gen_addi_i64(t2, t2, 32); 7160e28d006SRichard Henderson tcg_gen_clz_i64(t1, t1, t2); 7170e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 7180e28d006SRichard Henderson tcg_temp_free_i64(t1); 7190e28d006SRichard Henderson tcg_temp_free_i64(t2); 7200e28d006SRichard Henderson tcg_gen_subi_i32(ret, ret, 32); 7210e28d006SRichard Henderson } else { 7220e28d006SRichard Henderson gen_helper_clz_i32(ret, arg1, arg2); 7230e28d006SRichard Henderson } 7240e28d006SRichard Henderson } 7250e28d006SRichard Henderson 7260e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 7270e28d006SRichard Henderson { 72811d11d61SRichard Henderson tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2)); 7290e28d006SRichard Henderson } 7300e28d006SRichard Henderson 7310e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 7320e28d006SRichard Henderson { 7330e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i32) { 7340e28d006SRichard Henderson tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2); 7350e28d006SRichard Henderson } else if (TCG_TARGET_HAS_ctz_i64) { 7365dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 7375dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 7380e28d006SRichard Henderson tcg_gen_extu_i32_i64(t1, arg1); 7390e28d006SRichard Henderson tcg_gen_extu_i32_i64(t2, arg2); 7400e28d006SRichard Henderson tcg_gen_ctz_i64(t1, t1, t2); 7410e28d006SRichard Henderson tcg_gen_extrl_i64_i32(ret, t1); 7420e28d006SRichard Henderson tcg_temp_free_i64(t1); 7430e28d006SRichard Henderson tcg_temp_free_i64(t2); 74414e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i32 74514e99210SRichard Henderson || TCG_TARGET_HAS_ctpop_i64 74614e99210SRichard Henderson || TCG_TARGET_HAS_clz_i32 74714e99210SRichard Henderson || TCG_TARGET_HAS_clz_i64) { 7485dd48602SRichard Henderson TCGv_i32 z, t = tcg_temp_ebb_new_i32(); 74914e99210SRichard Henderson 75014e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) { 75114e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 75214e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 75314e99210SRichard Henderson tcg_gen_ctpop_i32(t, t); 75414e99210SRichard Henderson } else { 75514e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 32, don't fight it. */ 75614e99210SRichard Henderson tcg_gen_neg_i32(t, arg1); 75714e99210SRichard Henderson tcg_gen_and_i32(t, t, arg1); 75814e99210SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 75914e99210SRichard Henderson tcg_gen_xori_i32(t, t, 31); 76014e99210SRichard Henderson } 76111d11d61SRichard Henderson z = tcg_constant_i32(0); 76214e99210SRichard Henderson tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t); 76314e99210SRichard Henderson tcg_temp_free_i32(t); 7640e28d006SRichard Henderson } else { 7650e28d006SRichard Henderson gen_helper_ctz_i32(ret, arg1, arg2); 7660e28d006SRichard Henderson } 7670e28d006SRichard Henderson } 7680e28d006SRichard Henderson 7690e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) 7700e28d006SRichard Henderson { 77114e99210SRichard Henderson if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) { 77214e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 7735dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 77414e99210SRichard Henderson tcg_gen_subi_i32(t, arg1, 1); 77514e99210SRichard Henderson tcg_gen_andc_i32(t, t, arg1); 77614e99210SRichard Henderson tcg_gen_ctpop_i32(ret, t); 77714e99210SRichard Henderson tcg_temp_free_i32(t); 77814e99210SRichard Henderson } else { 77911d11d61SRichard Henderson tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2)); 7800e28d006SRichard Henderson } 78114e99210SRichard Henderson } 7820e28d006SRichard Henderson 783086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg) 784086920c2SRichard Henderson { 785086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i32) { 7865dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 787086920c2SRichard Henderson tcg_gen_sari_i32(t, arg, 31); 788086920c2SRichard Henderson tcg_gen_xor_i32(t, t, arg); 789086920c2SRichard Henderson tcg_gen_clzi_i32(t, t, 32); 790086920c2SRichard Henderson tcg_gen_subi_i32(ret, t, 1); 791086920c2SRichard Henderson tcg_temp_free_i32(t); 792086920c2SRichard Henderson } else { 793086920c2SRichard Henderson gen_helper_clrsb_i32(ret, arg); 794086920c2SRichard Henderson } 795086920c2SRichard Henderson } 796086920c2SRichard Henderson 797a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1) 798a768e4e9SRichard Henderson { 799a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i32) { 800a768e4e9SRichard Henderson tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1); 801a768e4e9SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64) { 8025dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 803a768e4e9SRichard Henderson tcg_gen_extu_i32_i64(t, arg1); 804a768e4e9SRichard Henderson tcg_gen_ctpop_i64(t, t); 805a768e4e9SRichard Henderson tcg_gen_extrl_i64_i32(ret, t); 806a768e4e9SRichard Henderson tcg_temp_free_i64(t); 807a768e4e9SRichard Henderson } else { 808a768e4e9SRichard Henderson gen_helper_ctpop_i32(ret, arg1); 809a768e4e9SRichard Henderson } 810a768e4e9SRichard Henderson } 811a768e4e9SRichard Henderson 812951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 813951c6300SRichard Henderson { 814951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 815951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2); 816951c6300SRichard Henderson } else { 817951c6300SRichard Henderson TCGv_i32 t0, t1; 818951c6300SRichard Henderson 8195dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 8205dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 821951c6300SRichard Henderson tcg_gen_shl_i32(t0, arg1, arg2); 822951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 823951c6300SRichard Henderson tcg_gen_shr_i32(t1, arg1, t1); 824951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 825951c6300SRichard Henderson tcg_temp_free_i32(t0); 826951c6300SRichard Henderson tcg_temp_free_i32(t1); 827951c6300SRichard Henderson } 828951c6300SRichard Henderson } 829951c6300SRichard Henderson 83007dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 831951c6300SRichard Henderson { 83207dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 833951c6300SRichard Henderson /* some cases can be optimized here */ 834951c6300SRichard Henderson if (arg2 == 0) { 835951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 836951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i32) { 83711d11d61SRichard Henderson tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2)); 838951c6300SRichard Henderson } else { 839951c6300SRichard Henderson TCGv_i32 t0, t1; 8405dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 8415dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 842951c6300SRichard Henderson tcg_gen_shli_i32(t0, arg1, arg2); 843951c6300SRichard Henderson tcg_gen_shri_i32(t1, arg1, 32 - arg2); 844951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 845951c6300SRichard Henderson tcg_temp_free_i32(t0); 846951c6300SRichard Henderson tcg_temp_free_i32(t1); 847951c6300SRichard Henderson } 848951c6300SRichard Henderson } 849951c6300SRichard Henderson 850951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 851951c6300SRichard Henderson { 852951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i32) { 853951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2); 854951c6300SRichard Henderson } else { 855951c6300SRichard Henderson TCGv_i32 t0, t1; 856951c6300SRichard Henderson 8575dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 8585dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 859951c6300SRichard Henderson tcg_gen_shr_i32(t0, arg1, arg2); 860951c6300SRichard Henderson tcg_gen_subfi_i32(t1, 32, arg2); 861951c6300SRichard Henderson tcg_gen_shl_i32(t1, arg1, t1); 862951c6300SRichard Henderson tcg_gen_or_i32(ret, t0, t1); 863951c6300SRichard Henderson tcg_temp_free_i32(t0); 864951c6300SRichard Henderson tcg_temp_free_i32(t1); 865951c6300SRichard Henderson } 866951c6300SRichard Henderson } 867951c6300SRichard Henderson 86807dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) 869951c6300SRichard Henderson { 87007dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 32); 871951c6300SRichard Henderson /* some cases can be optimized here */ 872951c6300SRichard Henderson if (arg2 == 0) { 873951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg1); 874951c6300SRichard Henderson } else { 875951c6300SRichard Henderson tcg_gen_rotli_i32(ret, arg1, 32 - arg2); 876951c6300SRichard Henderson } 877951c6300SRichard Henderson } 878951c6300SRichard Henderson 879951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, 880951c6300SRichard Henderson unsigned int ofs, unsigned int len) 881951c6300SRichard Henderson { 882951c6300SRichard Henderson uint32_t mask; 883951c6300SRichard Henderson TCGv_i32 t1; 884951c6300SRichard Henderson 885951c6300SRichard Henderson tcg_debug_assert(ofs < 32); 8860d0d309dSRichard Henderson tcg_debug_assert(len > 0); 887951c6300SRichard Henderson tcg_debug_assert(len <= 32); 888951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 32); 889951c6300SRichard Henderson 8900d0d309dSRichard Henderson if (len == 32) { 891951c6300SRichard Henderson tcg_gen_mov_i32(ret, arg2); 892951c6300SRichard Henderson return; 893951c6300SRichard Henderson } 894951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) { 895951c6300SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); 896951c6300SRichard Henderson return; 897951c6300SRichard Henderson } 898951c6300SRichard Henderson 8995dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 900951c6300SRichard Henderson 901b0a60567SRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 902b0a60567SRichard Henderson if (ofs + len == 32) { 903b0a60567SRichard Henderson tcg_gen_shli_i32(t1, arg1, len); 904b0a60567SRichard Henderson tcg_gen_extract2_i32(ret, t1, arg2, len); 905b0a60567SRichard Henderson goto done; 906b0a60567SRichard Henderson } 907b0a60567SRichard Henderson if (ofs == 0) { 908b0a60567SRichard Henderson tcg_gen_extract2_i32(ret, arg1, arg2, len); 909b0a60567SRichard Henderson tcg_gen_rotli_i32(ret, ret, len); 910b0a60567SRichard Henderson goto done; 911b0a60567SRichard Henderson } 912b0a60567SRichard Henderson } 913b0a60567SRichard Henderson 914b0a60567SRichard Henderson mask = (1u << len) - 1; 915951c6300SRichard Henderson if (ofs + len < 32) { 916951c6300SRichard Henderson tcg_gen_andi_i32(t1, arg2, mask); 917951c6300SRichard Henderson tcg_gen_shli_i32(t1, t1, ofs); 918951c6300SRichard Henderson } else { 919951c6300SRichard Henderson tcg_gen_shli_i32(t1, arg2, ofs); 920951c6300SRichard Henderson } 921951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg1, ~(mask << ofs)); 922951c6300SRichard Henderson tcg_gen_or_i32(ret, ret, t1); 923b0a60567SRichard Henderson done: 924951c6300SRichard Henderson tcg_temp_free_i32(t1); 925951c6300SRichard Henderson } 926951c6300SRichard Henderson 92707cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, 92807cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 92907cc68d5SRichard Henderson { 93007cc68d5SRichard Henderson tcg_debug_assert(ofs < 32); 93107cc68d5SRichard Henderson tcg_debug_assert(len > 0); 93207cc68d5SRichard Henderson tcg_debug_assert(len <= 32); 93307cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 32); 93407cc68d5SRichard Henderson 93507cc68d5SRichard Henderson if (ofs + len == 32) { 93607cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 93707cc68d5SRichard Henderson } else if (ofs == 0) { 93807cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 93907cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i32 94007cc68d5SRichard Henderson && TCG_TARGET_deposit_i32_valid(ofs, len)) { 94111d11d61SRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 94207cc68d5SRichard Henderson tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); 94307cc68d5SRichard Henderson } else { 94407cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 94507cc68d5SRichard Henderson which allows ARG to stay live. */ 94607cc68d5SRichard Henderson switch (len) { 94707cc68d5SRichard Henderson case 16: 94807cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 94907cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 95007cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 95107cc68d5SRichard Henderson return; 95207cc68d5SRichard Henderson } 95307cc68d5SRichard Henderson break; 95407cc68d5SRichard Henderson case 8: 95507cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 95607cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 95707cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 95807cc68d5SRichard Henderson return; 95907cc68d5SRichard Henderson } 96007cc68d5SRichard Henderson break; 96107cc68d5SRichard Henderson } 96207cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 96307cc68d5SRichard Henderson switch (ofs + len) { 96407cc68d5SRichard Henderson case 16: 96507cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 96607cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 96707cc68d5SRichard Henderson tcg_gen_ext16u_i32(ret, ret); 96807cc68d5SRichard Henderson return; 96907cc68d5SRichard Henderson } 97007cc68d5SRichard Henderson break; 97107cc68d5SRichard Henderson case 8: 97207cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 97307cc68d5SRichard Henderson tcg_gen_shli_i32(ret, arg, ofs); 97407cc68d5SRichard Henderson tcg_gen_ext8u_i32(ret, ret); 97507cc68d5SRichard Henderson return; 97607cc68d5SRichard Henderson } 97707cc68d5SRichard Henderson break; 97807cc68d5SRichard Henderson } 97907cc68d5SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 98007cc68d5SRichard Henderson tcg_gen_shli_i32(ret, ret, ofs); 98107cc68d5SRichard Henderson } 98207cc68d5SRichard Henderson } 98307cc68d5SRichard Henderson 9847ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, 9857ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 9867ec8bab3SRichard Henderson { 9877ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 9887ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 9897ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 9907ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 9917ec8bab3SRichard Henderson 9927ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 9937ec8bab3SRichard Henderson if (ofs + len == 32) { 9947ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, 32 - len); 9957ec8bab3SRichard Henderson return; 9967ec8bab3SRichard Henderson } 9977ec8bab3SRichard Henderson if (ofs == 0) { 9987ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, arg, (1u << len) - 1); 9997ec8bab3SRichard Henderson return; 10007ec8bab3SRichard Henderson } 10017ec8bab3SRichard Henderson 10027ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i32 10037ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 10047ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len); 10057ec8bab3SRichard Henderson return; 10067ec8bab3SRichard Henderson } 10077ec8bab3SRichard Henderson 10087ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 10097ec8bab3SRichard Henderson switch (ofs + len) { 10107ec8bab3SRichard Henderson case 16: 10117ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 10127ec8bab3SRichard Henderson tcg_gen_ext16u_i32(ret, arg); 10137ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 10147ec8bab3SRichard Henderson return; 10157ec8bab3SRichard Henderson } 10167ec8bab3SRichard Henderson break; 10177ec8bab3SRichard Henderson case 8: 10187ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 10197ec8bab3SRichard Henderson tcg_gen_ext8u_i32(ret, arg); 10207ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, ofs); 10217ec8bab3SRichard Henderson return; 10227ec8bab3SRichard Henderson } 10237ec8bab3SRichard Henderson break; 10247ec8bab3SRichard Henderson } 10257ec8bab3SRichard Henderson 10267ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 10277ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special case of 16, 10287ec8bab3SRichard Henderson so that we get ext8u, ext16u. */ 10297ec8bab3SRichard Henderson switch (len) { 10307ec8bab3SRichard Henderson case 1 ... 8: case 16: 10317ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 10327ec8bab3SRichard Henderson tcg_gen_andi_i32(ret, ret, (1u << len) - 1); 10337ec8bab3SRichard Henderson break; 10347ec8bab3SRichard Henderson default: 10357ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 10367ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, ret, 32 - len); 10377ec8bab3SRichard Henderson break; 10387ec8bab3SRichard Henderson } 10397ec8bab3SRichard Henderson } 10407ec8bab3SRichard Henderson 10417ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg, 10427ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 10437ec8bab3SRichard Henderson { 10447ec8bab3SRichard Henderson tcg_debug_assert(ofs < 32); 10457ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 10467ec8bab3SRichard Henderson tcg_debug_assert(len <= 32); 10477ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 32); 10487ec8bab3SRichard Henderson 10497ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 10507ec8bab3SRichard Henderson if (ofs + len == 32) { 10517ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, arg, 32 - len); 10527ec8bab3SRichard Henderson return; 10537ec8bab3SRichard Henderson } 10547ec8bab3SRichard Henderson if (ofs == 0) { 10557ec8bab3SRichard Henderson switch (len) { 10567ec8bab3SRichard Henderson case 16: 10577ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 10587ec8bab3SRichard Henderson return; 10597ec8bab3SRichard Henderson case 8: 10607ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 10617ec8bab3SRichard Henderson return; 10627ec8bab3SRichard Henderson } 10637ec8bab3SRichard Henderson } 10647ec8bab3SRichard Henderson 10657ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i32 10667ec8bab3SRichard Henderson && TCG_TARGET_extract_i32_valid(ofs, len)) { 10677ec8bab3SRichard Henderson tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); 10687ec8bab3SRichard Henderson return; 10697ec8bab3SRichard Henderson } 10707ec8bab3SRichard Henderson 10717ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 10727ec8bab3SRichard Henderson switch (ofs + len) { 10737ec8bab3SRichard Henderson case 16: 10747ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 10757ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, arg); 10767ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 10777ec8bab3SRichard Henderson return; 10787ec8bab3SRichard Henderson } 10797ec8bab3SRichard Henderson break; 10807ec8bab3SRichard Henderson case 8: 10817ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 10827ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, arg); 10837ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, ofs); 10847ec8bab3SRichard Henderson return; 10857ec8bab3SRichard Henderson } 10867ec8bab3SRichard Henderson break; 10877ec8bab3SRichard Henderson } 10887ec8bab3SRichard Henderson switch (len) { 10897ec8bab3SRichard Henderson case 16: 10907ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 10917ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 10927ec8bab3SRichard Henderson tcg_gen_ext16s_i32(ret, ret); 10937ec8bab3SRichard Henderson return; 10947ec8bab3SRichard Henderson } 10957ec8bab3SRichard Henderson break; 10967ec8bab3SRichard Henderson case 8: 10977ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 10987ec8bab3SRichard Henderson tcg_gen_shri_i32(ret, arg, ofs); 10997ec8bab3SRichard Henderson tcg_gen_ext8s_i32(ret, ret); 11007ec8bab3SRichard Henderson return; 11017ec8bab3SRichard Henderson } 11027ec8bab3SRichard Henderson break; 11037ec8bab3SRichard Henderson } 11047ec8bab3SRichard Henderson 11057ec8bab3SRichard Henderson tcg_gen_shli_i32(ret, arg, 32 - len - ofs); 11067ec8bab3SRichard Henderson tcg_gen_sari_i32(ret, ret, 32 - len); 11077ec8bab3SRichard Henderson } 11087ec8bab3SRichard Henderson 11092089fcc9SDavid Hildenbrand /* 11102089fcc9SDavid Hildenbrand * Extract 32-bits from a 64-bit input, ah:al, starting from ofs. 11112089fcc9SDavid Hildenbrand * Unlike tcg_gen_extract_i32 above, len is fixed at 32. 11122089fcc9SDavid Hildenbrand */ 11132089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah, 11142089fcc9SDavid Hildenbrand unsigned int ofs) 11152089fcc9SDavid Hildenbrand { 11162089fcc9SDavid Hildenbrand tcg_debug_assert(ofs <= 32); 11172089fcc9SDavid Hildenbrand if (ofs == 0) { 11182089fcc9SDavid Hildenbrand tcg_gen_mov_i32(ret, al); 11192089fcc9SDavid Hildenbrand } else if (ofs == 32) { 11202089fcc9SDavid Hildenbrand tcg_gen_mov_i32(ret, ah); 11212089fcc9SDavid Hildenbrand } else if (al == ah) { 11222089fcc9SDavid Hildenbrand tcg_gen_rotri_i32(ret, al, ofs); 1123fce1296fSRichard Henderson } else if (TCG_TARGET_HAS_extract2_i32) { 1124fce1296fSRichard Henderson tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs); 11252089fcc9SDavid Hildenbrand } else { 11265dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 11272089fcc9SDavid Hildenbrand tcg_gen_shri_i32(t0, al, ofs); 11282089fcc9SDavid Hildenbrand tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs); 11292089fcc9SDavid Hildenbrand tcg_temp_free_i32(t0); 11302089fcc9SDavid Hildenbrand } 11312089fcc9SDavid Hildenbrand } 11322089fcc9SDavid Hildenbrand 1133951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, 1134951c6300SRichard Henderson TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) 1135951c6300SRichard Henderson { 113637ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 113737ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v1); 113837ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 113937ed3bf1SRichard Henderson tcg_gen_mov_i32(ret, v2); 1140951c6300SRichard Henderson } else { 11413871be75SRichard Henderson tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond); 1142951c6300SRichard Henderson } 1143951c6300SRichard Henderson } 1144951c6300SRichard Henderson 1145951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 1146951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 1147951c6300SRichard Henderson { 1148951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i32) { 1149951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh); 1150951c6300SRichard Henderson } else { 11515dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 11525dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 1153951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 1154951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 1155951c6300SRichard Henderson tcg_gen_add_i64(t0, t0, t1); 1156951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 1157951c6300SRichard Henderson tcg_temp_free_i64(t0); 1158951c6300SRichard Henderson tcg_temp_free_i64(t1); 1159951c6300SRichard Henderson } 1160951c6300SRichard Henderson } 1161951c6300SRichard Henderson 1162951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, 1163951c6300SRichard Henderson TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) 1164951c6300SRichard Henderson { 1165951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i32) { 1166951c6300SRichard Henderson tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh); 1167951c6300SRichard Henderson } else { 11685dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 11695dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 1170951c6300SRichard Henderson tcg_gen_concat_i32_i64(t0, al, ah); 1171951c6300SRichard Henderson tcg_gen_concat_i32_i64(t1, bl, bh); 1172951c6300SRichard Henderson tcg_gen_sub_i64(t0, t0, t1); 1173951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 1174951c6300SRichard Henderson tcg_temp_free_i64(t0); 1175951c6300SRichard Henderson tcg_temp_free_i64(t1); 1176951c6300SRichard Henderson } 1177951c6300SRichard Henderson } 1178951c6300SRichard Henderson 1179951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 1180951c6300SRichard Henderson { 1181951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i32) { 1182951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); 1183951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i32) { 11845dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 1185951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 1186951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2); 1187951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 1188951c6300SRichard Henderson tcg_temp_free_i32(t); 11899fd86b51SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 11905dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 11915dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 1192951c6300SRichard Henderson tcg_gen_extu_i32_i64(t0, arg1); 1193951c6300SRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 1194951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 1195951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 1196951c6300SRichard Henderson tcg_temp_free_i64(t0); 1197951c6300SRichard Henderson tcg_temp_free_i64(t1); 11989fd86b51SRichard Henderson } else { 11999fd86b51SRichard Henderson qemu_build_not_reached(); 1200951c6300SRichard Henderson } 1201951c6300SRichard Henderson } 1202951c6300SRichard Henderson 1203951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 1204951c6300SRichard Henderson { 1205951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i32) { 1206951c6300SRichard Henderson tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); 1207951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i32) { 12085dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 1209951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); 1210951c6300SRichard Henderson tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2); 1211951c6300SRichard Henderson tcg_gen_mov_i32(rl, t); 1212951c6300SRichard Henderson tcg_temp_free_i32(t); 1213951c6300SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 12145dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 12155dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 12165dd48602SRichard Henderson TCGv_i32 t2 = tcg_temp_ebb_new_i32(); 12175dd48602SRichard Henderson TCGv_i32 t3 = tcg_temp_ebb_new_i32(); 1218951c6300SRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 1219951c6300SRichard Henderson /* Adjust for negative inputs. */ 1220951c6300SRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 1221951c6300SRichard Henderson tcg_gen_sari_i32(t3, arg2, 31); 1222951c6300SRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 1223951c6300SRichard Henderson tcg_gen_and_i32(t3, t3, arg1); 1224951c6300SRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 1225951c6300SRichard Henderson tcg_gen_sub_i32(rh, rh, t3); 1226951c6300SRichard Henderson tcg_gen_mov_i32(rl, t0); 1227951c6300SRichard Henderson tcg_temp_free_i32(t0); 1228951c6300SRichard Henderson tcg_temp_free_i32(t1); 1229951c6300SRichard Henderson tcg_temp_free_i32(t2); 1230951c6300SRichard Henderson tcg_temp_free_i32(t3); 1231951c6300SRichard Henderson } else { 12325dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 12335dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 1234951c6300SRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 1235951c6300SRichard Henderson tcg_gen_ext_i32_i64(t1, arg2); 1236951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 1237951c6300SRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 1238951c6300SRichard Henderson tcg_temp_free_i64(t0); 1239951c6300SRichard Henderson tcg_temp_free_i64(t1); 1240951c6300SRichard Henderson } 1241951c6300SRichard Henderson } 1242951c6300SRichard Henderson 12435087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) 12445087abfbSRichard Henderson { 12455087abfbSRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 12465dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 12475dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 12485dd48602SRichard Henderson TCGv_i32 t2 = tcg_temp_ebb_new_i32(); 12495087abfbSRichard Henderson tcg_gen_mulu2_i32(t0, t1, arg1, arg2); 12505087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 12515087abfbSRichard Henderson tcg_gen_sari_i32(t2, arg1, 31); 12525087abfbSRichard Henderson tcg_gen_and_i32(t2, t2, arg2); 12535087abfbSRichard Henderson tcg_gen_sub_i32(rh, t1, t2); 12545087abfbSRichard Henderson tcg_gen_mov_i32(rl, t0); 12555087abfbSRichard Henderson tcg_temp_free_i32(t0); 12565087abfbSRichard Henderson tcg_temp_free_i32(t1); 12575087abfbSRichard Henderson tcg_temp_free_i32(t2); 12585087abfbSRichard Henderson } else { 12595dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 12605dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 12615087abfbSRichard Henderson tcg_gen_ext_i32_i64(t0, arg1); 12625087abfbSRichard Henderson tcg_gen_extu_i32_i64(t1, arg2); 12635087abfbSRichard Henderson tcg_gen_mul_i64(t0, t0, t1); 12645087abfbSRichard Henderson tcg_gen_extr_i64_i32(rl, rh, t0); 12655087abfbSRichard Henderson tcg_temp_free_i64(t0); 12665087abfbSRichard Henderson tcg_temp_free_i64(t1); 12675087abfbSRichard Henderson } 12685087abfbSRichard Henderson } 12695087abfbSRichard Henderson 1270951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg) 1271951c6300SRichard Henderson { 1272951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8s_i32) { 1273951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg); 1274951c6300SRichard Henderson } else { 1275951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 24); 1276951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 24); 1277951c6300SRichard Henderson } 1278951c6300SRichard Henderson } 1279951c6300SRichard Henderson 1280951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg) 1281951c6300SRichard Henderson { 1282951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16s_i32) { 1283951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg); 1284951c6300SRichard Henderson } else { 1285951c6300SRichard Henderson tcg_gen_shli_i32(ret, arg, 16); 1286951c6300SRichard Henderson tcg_gen_sari_i32(ret, ret, 16); 1287951c6300SRichard Henderson } 1288951c6300SRichard Henderson } 1289951c6300SRichard Henderson 1290951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg) 1291951c6300SRichard Henderson { 1292951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i32) { 1293951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg); 1294951c6300SRichard Henderson } else { 1295951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffu); 1296951c6300SRichard Henderson } 1297951c6300SRichard Henderson } 1298951c6300SRichard Henderson 1299951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg) 1300951c6300SRichard Henderson { 1301951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i32) { 1302951c6300SRichard Henderson tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg); 1303951c6300SRichard Henderson } else { 1304951c6300SRichard Henderson tcg_gen_andi_i32(ret, arg, 0xffffu); 1305951c6300SRichard Henderson } 1306951c6300SRichard Henderson } 1307951c6300SRichard Henderson 13084de5a76aSPhilippe Mathieu-Daudé /* 13094de5a76aSPhilippe Mathieu-Daudé * bswap16_i32: 16-bit byte swap on the low bits of a 32-bit value. 13104de5a76aSPhilippe Mathieu-Daudé * 13114de5a76aSPhilippe Mathieu-Daudé * Byte pattern: xxab -> yyba 13124de5a76aSPhilippe Mathieu-Daudé * 13134de5a76aSPhilippe Mathieu-Daudé * With TCG_BSWAP_IZ, x == zero, else undefined. 13144de5a76aSPhilippe Mathieu-Daudé * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined. 13154de5a76aSPhilippe Mathieu-Daudé */ 13162b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags) 1317951c6300SRichard Henderson { 13182b836c2aSRichard Henderson /* Only one extension flag may be present. */ 13192b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 13202b836c2aSRichard Henderson 1321951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap16_i32) { 13222b836c2aSRichard Henderson tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags); 1323951c6300SRichard Henderson } else { 13245dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 13255dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 1326951c6300SRichard Henderson 13274de5a76aSPhilippe Mathieu-Daudé /* arg = ..ab (IZ) xxab (!IZ) */ 13284de5a76aSPhilippe Mathieu-Daudé tcg_gen_shri_i32(t0, arg, 8); /* t0 = ...a (IZ) .xxa (!IZ) */ 13292b836c2aSRichard Henderson if (!(flags & TCG_BSWAP_IZ)) { 13304de5a76aSPhilippe Mathieu-Daudé tcg_gen_ext8u_i32(t0, t0); /* t0 = ...a */ 13312b836c2aSRichard Henderson } 13322b836c2aSRichard Henderson 13332b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 13344de5a76aSPhilippe Mathieu-Daudé tcg_gen_shli_i32(t1, arg, 24); /* t1 = b... */ 13354de5a76aSPhilippe Mathieu-Daudé tcg_gen_sari_i32(t1, t1, 16); /* t1 = ssb. */ 13362b836c2aSRichard Henderson } else if (flags & TCG_BSWAP_OZ) { 13374de5a76aSPhilippe Mathieu-Daudé tcg_gen_ext8u_i32(t1, arg); /* t1 = ...b */ 13384de5a76aSPhilippe Mathieu-Daudé tcg_gen_shli_i32(t1, t1, 8); /* t1 = ..b. */ 13392b836c2aSRichard Henderson } else { 13404de5a76aSPhilippe Mathieu-Daudé tcg_gen_shli_i32(t1, arg, 8); /* t1 = xab. */ 13412b836c2aSRichard Henderson } 13422b836c2aSRichard Henderson 13434de5a76aSPhilippe Mathieu-Daudé tcg_gen_or_i32(ret, t0, t1); /* ret = ..ba (OZ) */ 13444de5a76aSPhilippe Mathieu-Daudé /* = ssba (OS) */ 13454de5a76aSPhilippe Mathieu-Daudé /* = xaba (no flag) */ 1346951c6300SRichard Henderson tcg_temp_free_i32(t0); 13472b836c2aSRichard Henderson tcg_temp_free_i32(t1); 1348951c6300SRichard Henderson } 1349951c6300SRichard Henderson } 1350951c6300SRichard Henderson 135192964556SPhilippe Mathieu-Daudé /* 135292964556SPhilippe Mathieu-Daudé * bswap32_i32: 32-bit byte swap on a 32-bit value. 135392964556SPhilippe Mathieu-Daudé * 135492964556SPhilippe Mathieu-Daudé * Byte pattern: abcd -> dcba 135592964556SPhilippe Mathieu-Daudé */ 1356951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg) 1357951c6300SRichard Henderson { 1358951c6300SRichard Henderson if (TCG_TARGET_HAS_bswap32_i32) { 1359587195bdSRichard Henderson tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0); 1360951c6300SRichard Henderson } else { 13615dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 13625dd48602SRichard Henderson TCGv_i32 t1 = tcg_temp_ebb_new_i32(); 136311d11d61SRichard Henderson TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff); 1364951c6300SRichard Henderson 1365a686dc71SRichard Henderson /* arg = abcd */ 1366a686dc71SRichard Henderson tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */ 1367a686dc71SRichard Henderson tcg_gen_and_i32(t1, arg, t2); /* t1 = .b.d */ 1368a686dc71SRichard Henderson tcg_gen_and_i32(t0, t0, t2); /* t0 = .a.c */ 1369a686dc71SRichard Henderson tcg_gen_shli_i32(t1, t1, 8); /* t1 = b.d. */ 1370a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = badc */ 1371951c6300SRichard Henderson 1372a686dc71SRichard Henderson tcg_gen_shri_i32(t0, ret, 16); /* t0 = ..ba */ 1373a686dc71SRichard Henderson tcg_gen_shli_i32(t1, ret, 16); /* t1 = dc.. */ 1374a686dc71SRichard Henderson tcg_gen_or_i32(ret, t0, t1); /* ret = dcba */ 1375951c6300SRichard Henderson 1376951c6300SRichard Henderson tcg_temp_free_i32(t0); 1377951c6300SRichard Henderson tcg_temp_free_i32(t1); 1378951c6300SRichard Henderson } 1379951c6300SRichard Henderson } 1380951c6300SRichard Henderson 1381b8976aa5SPhilippe Mathieu-Daudé /* 1382b8976aa5SPhilippe Mathieu-Daudé * hswap_i32: Swap 16-bit halfwords within a 32-bit value. 1383b8976aa5SPhilippe Mathieu-Daudé * 1384b8976aa5SPhilippe Mathieu-Daudé * Byte pattern: abcd -> cdab 1385b8976aa5SPhilippe Mathieu-Daudé */ 138646be8425SRichard Henderson void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg) 138746be8425SRichard Henderson { 138846be8425SRichard Henderson /* Swapping 2 16-bit elements is a rotate. */ 138946be8425SRichard Henderson tcg_gen_rotli_i32(ret, arg, 16); 139046be8425SRichard Henderson } 139146be8425SRichard Henderson 1392b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1393b87fb8cdSRichard Henderson { 1394b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); 1395b87fb8cdSRichard Henderson } 1396b87fb8cdSRichard Henderson 1397b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1398b87fb8cdSRichard Henderson { 1399b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); 1400b87fb8cdSRichard Henderson } 1401b87fb8cdSRichard Henderson 1402b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1403b87fb8cdSRichard Henderson { 1404b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); 1405b87fb8cdSRichard Henderson } 1406b87fb8cdSRichard Henderson 1407b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) 1408b87fb8cdSRichard Henderson { 1409b87fb8cdSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); 1410b87fb8cdSRichard Henderson } 1411b87fb8cdSRichard Henderson 1412ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a) 1413ff1f11f7SRichard Henderson { 14145dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 1415ff1f11f7SRichard Henderson 1416ff1f11f7SRichard Henderson tcg_gen_sari_i32(t, a, 31); 1417ff1f11f7SRichard Henderson tcg_gen_xor_i32(ret, a, t); 1418ff1f11f7SRichard Henderson tcg_gen_sub_i32(ret, ret, t); 1419ff1f11f7SRichard Henderson tcg_temp_free_i32(t); 1420ff1f11f7SRichard Henderson } 1421ff1f11f7SRichard Henderson 142209607d35SRichard Henderson void tcg_gen_ld8u_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset) 142309607d35SRichard Henderson { 142409607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_ld8u_i32, ret, arg2, offset); 142509607d35SRichard Henderson } 142609607d35SRichard Henderson 142709607d35SRichard Henderson void tcg_gen_ld8s_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset) 142809607d35SRichard Henderson { 142909607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_ld8s_i32, ret, arg2, offset); 143009607d35SRichard Henderson } 143109607d35SRichard Henderson 143209607d35SRichard Henderson void tcg_gen_ld16u_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset) 143309607d35SRichard Henderson { 143409607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_ld16u_i32, ret, arg2, offset); 143509607d35SRichard Henderson } 143609607d35SRichard Henderson 143709607d35SRichard Henderson void tcg_gen_ld16s_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset) 143809607d35SRichard Henderson { 143909607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_ld16s_i32, ret, arg2, offset); 144009607d35SRichard Henderson } 144109607d35SRichard Henderson 144209607d35SRichard Henderson void tcg_gen_ld_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset) 144309607d35SRichard Henderson { 144409607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_ld_i32, ret, arg2, offset); 144509607d35SRichard Henderson } 144609607d35SRichard Henderson 144709607d35SRichard Henderson void tcg_gen_st8_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset) 144809607d35SRichard Henderson { 144909607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_st8_i32, arg1, arg2, offset); 145009607d35SRichard Henderson } 145109607d35SRichard Henderson 145209607d35SRichard Henderson void tcg_gen_st16_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset) 145309607d35SRichard Henderson { 145409607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_st16_i32, arg1, arg2, offset); 145509607d35SRichard Henderson } 145609607d35SRichard Henderson 145709607d35SRichard Henderson void tcg_gen_st_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset) 145809607d35SRichard Henderson { 145909607d35SRichard Henderson tcg_gen_ldst_op_i32(INDEX_op_st_i32, arg1, arg2, offset); 146009607d35SRichard Henderson } 146109607d35SRichard Henderson 146209607d35SRichard Henderson 1463951c6300SRichard Henderson /* 64-bit ops */ 1464951c6300SRichard Henderson 1465951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg) 1466951c6300SRichard Henderson { 1467e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1468e0de2f55SRichard Henderson tcg_gen_op1_i64(INDEX_op_discard, arg); 1469e0de2f55SRichard Henderson } else { 1470951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_LOW(arg)); 1471951c6300SRichard Henderson tcg_gen_discard_i32(TCGV_HIGH(arg)); 1472951c6300SRichard Henderson } 1473e0de2f55SRichard Henderson } 1474951c6300SRichard Henderson 1475951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg) 1476951c6300SRichard Henderson { 1477e0de2f55SRichard Henderson if (ret == arg) { 1478e0de2f55SRichard Henderson return; 1479e0de2f55SRichard Henderson } 1480e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1481e0de2f55SRichard Henderson tcg_gen_op2_i64(INDEX_op_mov_i64, ret, arg); 1482e0de2f55SRichard Henderson } else { 148311d11d61SRichard Henderson TCGTemp *ts = tcgv_i64_temp(arg); 148411d11d61SRichard Henderson 148511d11d61SRichard Henderson /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */ 148611d11d61SRichard Henderson if (ts->kind == TEMP_CONST) { 148711d11d61SRichard Henderson tcg_gen_movi_i64(ret, ts->val); 148811d11d61SRichard Henderson } else { 1489951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 1490951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 1491951c6300SRichard Henderson } 149211d11d61SRichard Henderson } 1493e0de2f55SRichard Henderson } 1494951c6300SRichard Henderson 1495951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) 1496951c6300SRichard Henderson { 1497e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1498e0de2f55SRichard Henderson tcg_gen_mov_i64(ret, tcg_constant_i64(arg)); 1499e0de2f55SRichard Henderson } else { 1500951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), arg); 1501951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32); 1502951c6300SRichard Henderson } 1503e0de2f55SRichard Henderson } 1504951c6300SRichard Henderson 1505951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1506951c6300SRichard Henderson { 1507e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1508e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld8u_i64, ret, arg2, offset); 1509e0de2f55SRichard Henderson } else { 1510951c6300SRichard Henderson tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset); 1511951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1512951c6300SRichard Henderson } 1513e0de2f55SRichard Henderson } 1514951c6300SRichard Henderson 1515951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1516951c6300SRichard Henderson { 1517e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1518e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld8s_i64, ret, arg2, offset); 1519e0de2f55SRichard Henderson } else { 1520951c6300SRichard Henderson tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset); 15213ff91d7eSJoseph Myers tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1522951c6300SRichard Henderson } 1523e0de2f55SRichard Henderson } 1524951c6300SRichard Henderson 1525951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1526951c6300SRichard Henderson { 1527e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1528e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld16u_i64, ret, arg2, offset); 1529e0de2f55SRichard Henderson } else { 1530951c6300SRichard Henderson tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset); 1531951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1532951c6300SRichard Henderson } 1533e0de2f55SRichard Henderson } 1534951c6300SRichard Henderson 1535951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1536951c6300SRichard Henderson { 1537e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1538e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld16s_i64, ret, arg2, offset); 1539e0de2f55SRichard Henderson } else { 1540951c6300SRichard Henderson tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset); 1541951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1542951c6300SRichard Henderson } 1543e0de2f55SRichard Henderson } 1544951c6300SRichard Henderson 1545951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1546951c6300SRichard Henderson { 1547e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1548e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld32u_i64, ret, arg2, offset); 1549e0de2f55SRichard Henderson } else { 1550951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1551951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1552951c6300SRichard Henderson } 1553e0de2f55SRichard Henderson } 1554951c6300SRichard Henderson 1555951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1556951c6300SRichard Henderson { 1557e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1558e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld32s_i64, ret, arg2, offset); 1559e0de2f55SRichard Henderson } else { 1560951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1561951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 1562951c6300SRichard Henderson } 1563e0de2f55SRichard Henderson } 1564951c6300SRichard Henderson 1565951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) 1566951c6300SRichard Henderson { 1567e0de2f55SRichard Henderson /* 1568e0de2f55SRichard Henderson * For 32-bit host, since arg2 and ret have different types, 1569e0de2f55SRichard Henderson * they cannot be the same temporary -- no chance of overlap. 1570e0de2f55SRichard Henderson */ 1571e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1572e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_ld_i64, ret, arg2, offset); 1573e0de2f55SRichard Henderson } else if (HOST_BIG_ENDIAN) { 1574951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset); 1575951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4); 1576e0de2f55SRichard Henderson } else { 1577951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset); 1578951c6300SRichard Henderson tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4); 1579e0de2f55SRichard Henderson } 1580951c6300SRichard Henderson } 1581951c6300SRichard Henderson 1582d56fea79SRichard Henderson void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1583d56fea79SRichard Henderson { 1584e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1585e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_st8_i64, arg1, arg2, offset); 1586e0de2f55SRichard Henderson } else { 1587d56fea79SRichard Henderson tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset); 1588d56fea79SRichard Henderson } 1589e0de2f55SRichard Henderson } 1590d56fea79SRichard Henderson 1591d56fea79SRichard Henderson void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1592d56fea79SRichard Henderson { 1593e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1594e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_st16_i64, arg1, arg2, offset); 1595e0de2f55SRichard Henderson } else { 1596d56fea79SRichard Henderson tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset); 1597d56fea79SRichard Henderson } 1598e0de2f55SRichard Henderson } 1599d56fea79SRichard Henderson 1600d56fea79SRichard Henderson void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1601d56fea79SRichard Henderson { 1602e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1603e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_st32_i64, arg1, arg2, offset); 1604e0de2f55SRichard Henderson } else { 1605d56fea79SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1606d56fea79SRichard Henderson } 1607e0de2f55SRichard Henderson } 1608d56fea79SRichard Henderson 1609951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) 1610951c6300SRichard Henderson { 1611e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1612e0de2f55SRichard Henderson tcg_gen_ldst_op_i64(INDEX_op_st_i64, arg1, arg2, offset); 1613e0de2f55SRichard Henderson } else if (HOST_BIG_ENDIAN) { 1614951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset); 1615951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4); 1616e0de2f55SRichard Henderson } else { 1617951c6300SRichard Henderson tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset); 1618951c6300SRichard Henderson tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4); 1619e0de2f55SRichard Henderson } 1620951c6300SRichard Henderson } 1621951c6300SRichard Henderson 1622d56fea79SRichard Henderson void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1623d56fea79SRichard Henderson { 1624e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1625e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_add_i64, ret, arg1, arg2); 1626e0de2f55SRichard Henderson } else { 1627d56fea79SRichard Henderson tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1628d56fea79SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1629d56fea79SRichard Henderson } 1630e0de2f55SRichard Henderson } 1631d56fea79SRichard Henderson 1632d56fea79SRichard Henderson void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1633d56fea79SRichard Henderson { 1634e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1635e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_sub_i64, ret, arg1, arg2); 1636e0de2f55SRichard Henderson } else { 1637d56fea79SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), 1638d56fea79SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1639d56fea79SRichard Henderson } 1640e0de2f55SRichard Henderson } 1641d56fea79SRichard Henderson 1642951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1643951c6300SRichard Henderson { 1644e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1645e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_and_i64, ret, arg1, arg2); 1646e0de2f55SRichard Henderson } else { 1647951c6300SRichard Henderson tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1648951c6300SRichard Henderson tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1649951c6300SRichard Henderson } 1650e0de2f55SRichard Henderson } 1651951c6300SRichard Henderson 1652951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1653951c6300SRichard Henderson { 1654e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1655e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_or_i64, ret, arg1, arg2); 1656e0de2f55SRichard Henderson } else { 1657951c6300SRichard Henderson tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1658951c6300SRichard Henderson tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1659951c6300SRichard Henderson } 1660e0de2f55SRichard Henderson } 1661951c6300SRichard Henderson 1662951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1663951c6300SRichard Henderson { 1664e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1665e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_xor_i64, ret, arg1, arg2); 1666e0de2f55SRichard Henderson } else { 1667951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 1668951c6300SRichard Henderson tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 1669951c6300SRichard Henderson } 1670e0de2f55SRichard Henderson } 1671951c6300SRichard Henderson 1672951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1673951c6300SRichard Henderson { 1674e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1675e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_shl_i64, ret, arg1, arg2); 1676e0de2f55SRichard Henderson } else { 1677951c6300SRichard Henderson gen_helper_shl_i64(ret, arg1, arg2); 1678951c6300SRichard Henderson } 1679e0de2f55SRichard Henderson } 1680951c6300SRichard Henderson 1681951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1682951c6300SRichard Henderson { 1683e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1684e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_shr_i64, ret, arg1, arg2); 1685e0de2f55SRichard Henderson } else { 1686951c6300SRichard Henderson gen_helper_shr_i64(ret, arg1, arg2); 1687951c6300SRichard Henderson } 1688e0de2f55SRichard Henderson } 1689951c6300SRichard Henderson 1690951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1691951c6300SRichard Henderson { 1692e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1693e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_sar_i64, ret, arg1, arg2); 1694e0de2f55SRichard Henderson } else { 1695951c6300SRichard Henderson gen_helper_sar_i64(ret, arg1, arg2); 1696951c6300SRichard Henderson } 1697e0de2f55SRichard Henderson } 1698951c6300SRichard Henderson 1699951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 1700951c6300SRichard Henderson { 1701951c6300SRichard Henderson TCGv_i64 t0; 1702951c6300SRichard Henderson TCGv_i32 t1; 1703951c6300SRichard Henderson 1704e0de2f55SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1705e0de2f55SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, ret, arg1, arg2); 1706e0de2f55SRichard Henderson return; 1707e0de2f55SRichard Henderson } 1708e0de2f55SRichard Henderson 1709e0de2f55SRichard Henderson 17105dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 17115dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 1712951c6300SRichard Henderson 1713951c6300SRichard Henderson tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0), 1714951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_LOW(arg2)); 1715951c6300SRichard Henderson 1716951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); 1717951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1718951c6300SRichard Henderson tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2)); 1719951c6300SRichard Henderson tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); 1720951c6300SRichard Henderson 1721951c6300SRichard Henderson tcg_gen_mov_i64(ret, t0); 1722951c6300SRichard Henderson tcg_temp_free_i64(t0); 1723951c6300SRichard Henderson tcg_temp_free_i32(t1); 1724951c6300SRichard Henderson } 172511d11d61SRichard Henderson 1726951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1727951c6300SRichard Henderson { 1728951c6300SRichard Henderson /* some cases can be optimized here */ 1729951c6300SRichard Henderson if (arg2 == 0) { 1730951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 173111d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 173211d11d61SRichard Henderson tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2)); 1733951c6300SRichard Henderson } else { 173411d11d61SRichard Henderson tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 173511d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 173611d11d61SRichard Henderson tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1737951c6300SRichard Henderson } 1738951c6300SRichard Henderson } 1739951c6300SRichard Henderson 1740951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2) 1741951c6300SRichard Henderson { 1742*b701f195SRichard Henderson if (arg1 == 0) { 1743*b701f195SRichard Henderson tcg_gen_neg_i64(ret, arg2); 174411d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 174511d11d61SRichard Henderson tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2); 1746951c6300SRichard Henderson } else { 174711d11d61SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 174811d11d61SRichard Henderson tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32), 174911d11d61SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2)); 1750951c6300SRichard Henderson } 1751951c6300SRichard Henderson } 1752951c6300SRichard Henderson 1753951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1754951c6300SRichard Henderson { 1755951c6300SRichard Henderson /* some cases can be optimized here */ 1756951c6300SRichard Henderson if (arg2 == 0) { 1757951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 175811d11d61SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 175911d11d61SRichard Henderson tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2)); 1760951c6300SRichard Henderson } else { 176111d11d61SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 176211d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 176311d11d61SRichard Henderson tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32)); 1764951c6300SRichard Henderson } 1765951c6300SRichard Henderson } 1766951c6300SRichard Henderson 1767e0de2f55SRichard Henderson void tcg_gen_neg_i64(TCGv_i64 ret, TCGv_i64 arg) 1768e0de2f55SRichard Henderson { 1769*b701f195SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 1770e0de2f55SRichard Henderson tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg); 1771e0de2f55SRichard Henderson } else { 1772*b701f195SRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 1773*b701f195SRichard Henderson tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), 1774*b701f195SRichard Henderson zero, zero, TCGV_LOW(arg), TCGV_HIGH(arg)); 1775e0de2f55SRichard Henderson } 1776e0de2f55SRichard Henderson } 1777e0de2f55SRichard Henderson 1778474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1779951c6300SRichard Henderson { 17803a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1781951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1782951c6300SRichard Henderson tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 17833a13c3f3SRichard Henderson return; 17843a13c3f3SRichard Henderson } 17853a13c3f3SRichard Henderson 1786951c6300SRichard Henderson /* Some cases can be optimized here. */ 1787951c6300SRichard Henderson switch (arg2) { 1788951c6300SRichard Henderson case 0: 1789951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1790951c6300SRichard Henderson return; 1791474b2e8fSRichard Henderson case -1: 1792951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1793951c6300SRichard Henderson return; 1794474b2e8fSRichard Henderson case 0xff: 1795951c6300SRichard Henderson /* Don't recurse with tcg_gen_ext8u_i64. */ 1796951c6300SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 1797951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1); 1798951c6300SRichard Henderson return; 1799951c6300SRichard Henderson } 1800951c6300SRichard Henderson break; 1801474b2e8fSRichard Henderson case 0xffff: 1802951c6300SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 1803951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1); 1804951c6300SRichard Henderson return; 1805951c6300SRichard Henderson } 1806951c6300SRichard Henderson break; 1807474b2e8fSRichard Henderson case 0xffffffffu: 1808951c6300SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 1809951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1); 1810951c6300SRichard Henderson return; 1811951c6300SRichard Henderson } 1812951c6300SRichard Henderson break; 1813951c6300SRichard Henderson } 181411d11d61SRichard Henderson 181511d11d61SRichard Henderson tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2)); 1816951c6300SRichard Henderson } 1817951c6300SRichard Henderson 1818951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1819951c6300SRichard Henderson { 18203a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1821951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1822951c6300SRichard Henderson tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 18233a13c3f3SRichard Henderson return; 18243a13c3f3SRichard Henderson } 1825951c6300SRichard Henderson /* Some cases can be optimized here. */ 1826951c6300SRichard Henderson if (arg2 == -1) { 1827951c6300SRichard Henderson tcg_gen_movi_i64(ret, -1); 1828951c6300SRichard Henderson } else if (arg2 == 0) { 1829951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1830951c6300SRichard Henderson } else { 183111d11d61SRichard Henderson tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2)); 1832951c6300SRichard Henderson } 1833951c6300SRichard Henderson } 1834951c6300SRichard Henderson 1835951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1836951c6300SRichard Henderson { 18373a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1838951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2); 1839951c6300SRichard Henderson tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32); 18403a13c3f3SRichard Henderson return; 18413a13c3f3SRichard Henderson } 1842951c6300SRichard Henderson /* Some cases can be optimized here. */ 1843951c6300SRichard Henderson if (arg2 == 0) { 1844951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1845951c6300SRichard Henderson } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) { 1846951c6300SRichard Henderson /* Don't recurse with tcg_gen_not_i64. */ 1847951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1); 1848951c6300SRichard Henderson } else { 184911d11d61SRichard Henderson tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2)); 1850951c6300SRichard Henderson } 1851951c6300SRichard Henderson } 1852951c6300SRichard Henderson 1853951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, 1854951c6300SRichard Henderson unsigned c, bool right, bool arith) 1855951c6300SRichard Henderson { 1856951c6300SRichard Henderson tcg_debug_assert(c < 64); 1857951c6300SRichard Henderson if (c == 0) { 1858951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 1859951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 1860951c6300SRichard Henderson } else if (c >= 32) { 1861951c6300SRichard Henderson c -= 32; 1862951c6300SRichard Henderson if (right) { 1863951c6300SRichard Henderson if (arith) { 1864951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1865951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); 1866951c6300SRichard Henderson } else { 1867951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 1868951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 1869951c6300SRichard Henderson } 1870951c6300SRichard Henderson } else { 1871951c6300SRichard Henderson tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c); 1872951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 1873951c6300SRichard Henderson } 187402616badSRichard Henderson } else if (right) { 187502616badSRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 187602616badSRichard Henderson tcg_gen_extract2_i32(TCGV_LOW(ret), 187702616badSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), c); 1878951c6300SRichard Henderson } else { 1879951c6300SRichard Henderson tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 188002616badSRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret), 188102616badSRichard Henderson TCGV_HIGH(arg1), 32 - c, c); 1882951c6300SRichard Henderson } 188302616badSRichard Henderson if (arith) { 188402616badSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 188502616badSRichard Henderson } else { 188602616badSRichard Henderson tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 188702616badSRichard Henderson } 188802616badSRichard Henderson } else { 188902616badSRichard Henderson if (TCG_TARGET_HAS_extract2_i32) { 189002616badSRichard Henderson tcg_gen_extract2_i32(TCGV_HIGH(ret), 189102616badSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c); 189202616badSRichard Henderson } else { 18935dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 189402616badSRichard Henderson tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c); 189502616badSRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), t0, 189602616badSRichard Henderson TCGV_HIGH(arg1), c, 32 - c); 1897951c6300SRichard Henderson tcg_temp_free_i32(t0); 189802616badSRichard Henderson } 189902616badSRichard Henderson tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 1900951c6300SRichard Henderson } 1901951c6300SRichard Henderson } 1902951c6300SRichard Henderson 1903474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1904951c6300SRichard Henderson { 1905474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 19063a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19073a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0); 19083a13c3f3SRichard Henderson } else if (arg2 == 0) { 1909951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1910951c6300SRichard Henderson } else { 191111d11d61SRichard Henderson tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2)); 1912951c6300SRichard Henderson } 1913951c6300SRichard Henderson } 1914951c6300SRichard Henderson 1915474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1916951c6300SRichard Henderson { 1917474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 19183a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19193a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0); 19203a13c3f3SRichard Henderson } else if (arg2 == 0) { 1921951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1922951c6300SRichard Henderson } else { 192311d11d61SRichard Henderson tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2)); 1924951c6300SRichard Henderson } 1925951c6300SRichard Henderson } 1926951c6300SRichard Henderson 1927474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 1928951c6300SRichard Henderson { 1929474b2e8fSRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 19303a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 19313a13c3f3SRichard Henderson tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1); 19323a13c3f3SRichard Henderson } else if (arg2 == 0) { 1933951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 1934951c6300SRichard Henderson } else { 193511d11d61SRichard Henderson tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2)); 1936951c6300SRichard Henderson } 1937951c6300SRichard Henderson } 1938951c6300SRichard Henderson 193942a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l) 1940951c6300SRichard Henderson { 1941951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 194242a268c2SRichard Henderson tcg_gen_br(l); 1943951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 19443a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1945951c6300SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1), 1946951c6300SRichard Henderson TCGV_HIGH(arg1), TCGV_LOW(arg2), 194742a268c2SRichard Henderson TCGV_HIGH(arg2), cond, label_arg(l)); 19483a13c3f3SRichard Henderson } else { 194942a268c2SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, 195042a268c2SRichard Henderson label_arg(l)); 19513a13c3f3SRichard Henderson } 1952f85b1fc4SRichard Henderson add_last_as_label_use(l); 1953951c6300SRichard Henderson } 1954951c6300SRichard Henderson } 1955951c6300SRichard Henderson 195642a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l) 1957951c6300SRichard Henderson { 195811d11d61SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 195911d11d61SRichard Henderson tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l); 196011d11d61SRichard Henderson } else if (cond == TCG_COND_ALWAYS) { 196142a268c2SRichard Henderson tcg_gen_br(l); 1962951c6300SRichard Henderson } else if (cond != TCG_COND_NEVER) { 196311d11d61SRichard Henderson tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, 196411d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 196511d11d61SRichard Henderson tcg_constant_i32(arg2), 196611d11d61SRichard Henderson tcg_constant_i32(arg2 >> 32), 196711d11d61SRichard Henderson cond, label_arg(l)); 1968f85b1fc4SRichard Henderson add_last_as_label_use(l); 1969951c6300SRichard Henderson } 1970951c6300SRichard Henderson } 1971951c6300SRichard Henderson 1972951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, 1973951c6300SRichard Henderson TCGv_i64 arg1, TCGv_i64 arg2) 1974951c6300SRichard Henderson { 1975951c6300SRichard Henderson if (cond == TCG_COND_ALWAYS) { 1976951c6300SRichard Henderson tcg_gen_movi_i64(ret, 1); 1977951c6300SRichard Henderson } else if (cond == TCG_COND_NEVER) { 1978951c6300SRichard Henderson tcg_gen_movi_i64(ret, 0); 1979951c6300SRichard Henderson } else { 19803a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 1981951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 1982951c6300SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 1983951c6300SRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 1984951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 19853a13c3f3SRichard Henderson } else { 1986951c6300SRichard Henderson tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); 19873a13c3f3SRichard Henderson } 1988951c6300SRichard Henderson } 1989951c6300SRichard Henderson } 1990951c6300SRichard Henderson 1991951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, 1992951c6300SRichard Henderson TCGv_i64 arg1, int64_t arg2) 1993951c6300SRichard Henderson { 199411d11d61SRichard Henderson if (TCG_TARGET_REG_BITS == 64) { 199511d11d61SRichard Henderson tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2)); 199611d11d61SRichard Henderson } else if (cond == TCG_COND_ALWAYS) { 199711d11d61SRichard Henderson tcg_gen_movi_i64(ret, 1); 199811d11d61SRichard Henderson } else if (cond == TCG_COND_NEVER) { 199911d11d61SRichard Henderson tcg_gen_movi_i64(ret, 0); 200011d11d61SRichard Henderson } else { 200111d11d61SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 200211d11d61SRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 200311d11d61SRichard Henderson tcg_constant_i32(arg2), 200411d11d61SRichard Henderson tcg_constant_i32(arg2 >> 32), cond); 200511d11d61SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 200611d11d61SRichard Henderson } 2007951c6300SRichard Henderson } 2008951c6300SRichard Henderson 200993c86ecdSPaolo Bonzini void tcg_gen_negsetcondi_i64(TCGCond cond, TCGv_i64 ret, 201093c86ecdSPaolo Bonzini TCGv_i64 arg1, int64_t arg2) 201193c86ecdSPaolo Bonzini { 201293c86ecdSPaolo Bonzini tcg_gen_negsetcond_i64(cond, ret, arg1, tcg_constant_i64(arg2)); 201393c86ecdSPaolo Bonzini } 201493c86ecdSPaolo Bonzini 20153635502dSRichard Henderson void tcg_gen_negsetcond_i64(TCGCond cond, TCGv_i64 ret, 20163635502dSRichard Henderson TCGv_i64 arg1, TCGv_i64 arg2) 20173635502dSRichard Henderson { 20183635502dSRichard Henderson if (cond == TCG_COND_ALWAYS) { 20193635502dSRichard Henderson tcg_gen_movi_i64(ret, -1); 20203635502dSRichard Henderson } else if (cond == TCG_COND_NEVER) { 20213635502dSRichard Henderson tcg_gen_movi_i64(ret, 0); 20223635502dSRichard Henderson } else if (TCG_TARGET_HAS_negsetcond_i64) { 20233635502dSRichard Henderson tcg_gen_op4i_i64(INDEX_op_negsetcond_i64, ret, arg1, arg2, cond); 20243635502dSRichard Henderson } else if (TCG_TARGET_REG_BITS == 32) { 20253635502dSRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), 20263635502dSRichard Henderson TCGV_LOW(arg1), TCGV_HIGH(arg1), 20273635502dSRichard Henderson TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); 20283635502dSRichard Henderson tcg_gen_neg_i32(TCGV_LOW(ret), TCGV_LOW(ret)); 20293635502dSRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_LOW(ret)); 20303635502dSRichard Henderson } else { 20313635502dSRichard Henderson tcg_gen_setcond_i64(cond, ret, arg1, arg2); 20323635502dSRichard Henderson tcg_gen_neg_i64(ret, ret); 20333635502dSRichard Henderson } 20343635502dSRichard Henderson } 20353635502dSRichard Henderson 2036951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2037951c6300SRichard Henderson { 2038b2e3ae94SRichard Henderson if (arg2 == 0) { 2039b2e3ae94SRichard Henderson tcg_gen_movi_i64(ret, 0); 2040b2e3ae94SRichard Henderson } else if (is_power_of_2(arg2)) { 2041b2e3ae94SRichard Henderson tcg_gen_shli_i64(ret, arg1, ctz64(arg2)); 2042b2e3ae94SRichard Henderson } else { 2043f04de891SRichard Henderson tcg_gen_mul_i64(ret, arg1, tcg_constant_i64(arg2)); 2044951c6300SRichard Henderson } 2045b2e3ae94SRichard Henderson } 2046951c6300SRichard Henderson 2047951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2048951c6300SRichard Henderson { 2049951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 2050951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2); 2051951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 20525dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2053951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 2054951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2); 2055951c6300SRichard Henderson tcg_temp_free_i64(t0); 2056951c6300SRichard Henderson } else { 2057951c6300SRichard Henderson gen_helper_div_i64(ret, arg1, arg2); 2058951c6300SRichard Henderson } 2059951c6300SRichard Henderson } 2060951c6300SRichard Henderson 2061951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2062951c6300SRichard Henderson { 2063951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 2064951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2); 2065951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 20665dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2067951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2); 2068951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 2069951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 2070951c6300SRichard Henderson tcg_temp_free_i64(t0); 2071951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 20725dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2073951c6300SRichard Henderson tcg_gen_sari_i64(t0, arg1, 63); 2074951c6300SRichard Henderson tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2); 2075951c6300SRichard Henderson tcg_temp_free_i64(t0); 2076951c6300SRichard Henderson } else { 2077951c6300SRichard Henderson gen_helper_rem_i64(ret, arg1, arg2); 2078951c6300SRichard Henderson } 2079951c6300SRichard Henderson } 2080951c6300SRichard Henderson 2081951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2082951c6300SRichard Henderson { 2083951c6300SRichard Henderson if (TCG_TARGET_HAS_div_i64) { 2084951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2); 2085951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 20865dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2087bfefdbeaSRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 2088bfefdbeaSRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, zero, arg2); 2089951c6300SRichard Henderson tcg_temp_free_i64(t0); 2090951c6300SRichard Henderson } else { 2091951c6300SRichard Henderson gen_helper_divu_i64(ret, arg1, arg2); 2092951c6300SRichard Henderson } 2093951c6300SRichard Henderson } 2094951c6300SRichard Henderson 2095951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2096951c6300SRichard Henderson { 2097951c6300SRichard Henderson if (TCG_TARGET_HAS_rem_i64) { 2098951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); 2099951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div_i64) { 21005dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2101951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2); 2102951c6300SRichard Henderson tcg_gen_mul_i64(t0, t0, arg2); 2103951c6300SRichard Henderson tcg_gen_sub_i64(ret, arg1, t0); 2104951c6300SRichard Henderson tcg_temp_free_i64(t0); 2105951c6300SRichard Henderson } else if (TCG_TARGET_HAS_div2_i64) { 21065dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2107bfefdbeaSRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 2108bfefdbeaSRichard Henderson tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, zero, arg2); 2109951c6300SRichard Henderson tcg_temp_free_i64(t0); 2110951c6300SRichard Henderson } else { 2111951c6300SRichard Henderson gen_helper_remu_i64(ret, arg1, arg2); 2112951c6300SRichard Henderson } 2113951c6300SRichard Henderson } 2114951c6300SRichard Henderson 2115951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg) 2116951c6300SRichard Henderson { 21173a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2118951c6300SRichard Henderson tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2119951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 21203a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8s_i64) { 2121951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg); 2122951c6300SRichard Henderson } else { 2123951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 56); 2124951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 56); 2125951c6300SRichard Henderson } 2126951c6300SRichard Henderson } 2127951c6300SRichard Henderson 2128951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg) 2129951c6300SRichard Henderson { 21303a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2131951c6300SRichard Henderson tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2132951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 21333a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16s_i64) { 2134951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg); 2135951c6300SRichard Henderson } else { 2136951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 48); 2137951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 48); 2138951c6300SRichard Henderson } 2139951c6300SRichard Henderson } 2140951c6300SRichard Henderson 2141951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg) 2142951c6300SRichard Henderson { 21433a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2144951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2145951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 21463a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32s_i64) { 2147951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg); 2148951c6300SRichard Henderson } else { 2149951c6300SRichard Henderson tcg_gen_shli_i64(ret, arg, 32); 2150951c6300SRichard Henderson tcg_gen_sari_i64(ret, ret, 32); 2151951c6300SRichard Henderson } 2152951c6300SRichard Henderson } 2153951c6300SRichard Henderson 2154951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg) 2155951c6300SRichard Henderson { 21563a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2157951c6300SRichard Henderson tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2158951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 21593a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext8u_i64) { 2160951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg); 2161951c6300SRichard Henderson } else { 2162951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffu); 2163951c6300SRichard Henderson } 2164951c6300SRichard Henderson } 2165951c6300SRichard Henderson 2166951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg) 2167951c6300SRichard Henderson { 21683a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2169951c6300SRichard Henderson tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2170951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 21713a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext16u_i64) { 2172951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg); 2173951c6300SRichard Henderson } else { 2174951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffu); 2175951c6300SRichard Henderson } 2176951c6300SRichard Henderson } 2177951c6300SRichard Henderson 2178951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg) 2179951c6300SRichard Henderson { 21803a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2181951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 2182951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 21833a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_ext32u_i64) { 2184951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg); 2185951c6300SRichard Henderson } else { 2186951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg, 0xffffffffu); 2187951c6300SRichard Henderson } 2188951c6300SRichard Henderson } 2189951c6300SRichard Henderson 21908b078800SPhilippe Mathieu-Daudé /* 21918b078800SPhilippe Mathieu-Daudé * bswap16_i64: 16-bit byte swap on the low bits of a 64-bit value. 21928b078800SPhilippe Mathieu-Daudé * 21938b078800SPhilippe Mathieu-Daudé * Byte pattern: xxxxxxxxab -> yyyyyyyyba 21948b078800SPhilippe Mathieu-Daudé * 21958b078800SPhilippe Mathieu-Daudé * With TCG_BSWAP_IZ, x == zero, else undefined. 21968b078800SPhilippe Mathieu-Daudé * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined. 21978b078800SPhilippe Mathieu-Daudé */ 21982b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 2199951c6300SRichard Henderson { 22002b836c2aSRichard Henderson /* Only one extension flag may be present. */ 22012b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 22022b836c2aSRichard Henderson 22033a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 22042b836c2aSRichard Henderson tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags); 22052b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 22062b836c2aSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 22072b836c2aSRichard Henderson } else { 2208951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 22092b836c2aSRichard Henderson } 22103a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap16_i64) { 22112b836c2aSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags); 2212951c6300SRichard Henderson } else { 22135dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 22145dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 2215951c6300SRichard Henderson 22168b078800SPhilippe Mathieu-Daudé /* arg = ......ab or xxxxxxab */ 22178b078800SPhilippe Mathieu-Daudé tcg_gen_shri_i64(t0, arg, 8); /* t0 = .......a or .xxxxxxa */ 22182b836c2aSRichard Henderson if (!(flags & TCG_BSWAP_IZ)) { 22198b078800SPhilippe Mathieu-Daudé tcg_gen_ext8u_i64(t0, t0); /* t0 = .......a */ 22202b836c2aSRichard Henderson } 22212b836c2aSRichard Henderson 22222b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 22238b078800SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t1, arg, 56); /* t1 = b....... */ 22248b078800SPhilippe Mathieu-Daudé tcg_gen_sari_i64(t1, t1, 48); /* t1 = ssssssb. */ 22252b836c2aSRichard Henderson } else if (flags & TCG_BSWAP_OZ) { 22268b078800SPhilippe Mathieu-Daudé tcg_gen_ext8u_i64(t1, arg); /* t1 = .......b */ 22278b078800SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t1, t1, 8); /* t1 = ......b. */ 22282b836c2aSRichard Henderson } else { 22298b078800SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t1, arg, 8); /* t1 = xxxxxab. */ 22302b836c2aSRichard Henderson } 22312b836c2aSRichard Henderson 22328b078800SPhilippe Mathieu-Daudé tcg_gen_or_i64(ret, t0, t1); /* ret = ......ba (OZ) */ 22338b078800SPhilippe Mathieu-Daudé /* ssssssba (OS) */ 22348b078800SPhilippe Mathieu-Daudé /* xxxxxaba (no flag) */ 2235951c6300SRichard Henderson tcg_temp_free_i64(t0); 22362b836c2aSRichard Henderson tcg_temp_free_i64(t1); 2237951c6300SRichard Henderson } 2238951c6300SRichard Henderson } 2239951c6300SRichard Henderson 22409c406215SPhilippe Mathieu-Daudé /* 22419c406215SPhilippe Mathieu-Daudé * bswap32_i64: 32-bit byte swap on the low bits of a 64-bit value. 22429c406215SPhilippe Mathieu-Daudé * 22439c406215SPhilippe Mathieu-Daudé * Byte pattern: xxxxabcd -> yyyydcba 22449c406215SPhilippe Mathieu-Daudé * 22459c406215SPhilippe Mathieu-Daudé * With TCG_BSWAP_IZ, x == zero, else undefined. 22469c406215SPhilippe Mathieu-Daudé * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined. 22479c406215SPhilippe Mathieu-Daudé */ 22482b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) 2249951c6300SRichard Henderson { 22502b836c2aSRichard Henderson /* Only one extension flag may be present. */ 22512b836c2aSRichard Henderson tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ)); 22522b836c2aSRichard Henderson 22533a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2254951c6300SRichard Henderson tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 22552b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 22562b836c2aSRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 22572b836c2aSRichard Henderson } else { 2258951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 22592b836c2aSRichard Henderson } 22603a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap32_i64) { 22612b836c2aSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags); 2262951c6300SRichard Henderson } else { 22635dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 22645dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 226511d11d61SRichard Henderson TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff); 2266951c6300SRichard Henderson 22672b836c2aSRichard Henderson /* arg = xxxxabcd */ 22682b836c2aSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .xxxxabc */ 2269a686dc71SRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */ 2270a686dc71SRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */ 2271a686dc71SRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */ 2272a686dc71SRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */ 2273951c6300SRichard Henderson 2274a686dc71SRichard Henderson tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */ 2275a686dc71SRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */ 22762b836c2aSRichard Henderson if (flags & TCG_BSWAP_OS) { 22772b836c2aSRichard Henderson tcg_gen_sari_i64(t1, t1, 32); /* t1 = ssssdc.. */ 22782b836c2aSRichard Henderson } else { 2279a686dc71SRichard Henderson tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */ 22802b836c2aSRichard Henderson } 22819c406215SPhilippe Mathieu-Daudé tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba (OS) */ 22829c406215SPhilippe Mathieu-Daudé /* ....dcba (else) */ 2283951c6300SRichard Henderson 2284951c6300SRichard Henderson tcg_temp_free_i64(t0); 2285951c6300SRichard Henderson tcg_temp_free_i64(t1); 2286951c6300SRichard Henderson } 2287951c6300SRichard Henderson } 2288951c6300SRichard Henderson 228995180e75SPhilippe Mathieu-Daudé /* 229095180e75SPhilippe Mathieu-Daudé * bswap64_i64: 64-bit byte swap on a 64-bit value. 229195180e75SPhilippe Mathieu-Daudé * 229295180e75SPhilippe Mathieu-Daudé * Byte pattern: abcdefgh -> hgfedcba 229395180e75SPhilippe Mathieu-Daudé */ 2294951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg) 2295951c6300SRichard Henderson { 22963a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2297951c6300SRichard Henderson TCGv_i32 t0, t1; 22985dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i32(); 22995dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i32(); 2300951c6300SRichard Henderson 2301951c6300SRichard Henderson tcg_gen_bswap32_i32(t0, TCGV_LOW(arg)); 2302951c6300SRichard Henderson tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg)); 2303951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), t1); 2304951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t0); 2305951c6300SRichard Henderson tcg_temp_free_i32(t0); 2306951c6300SRichard Henderson tcg_temp_free_i32(t1); 23073a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_bswap64_i64) { 2308587195bdSRichard Henderson tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0); 2309951c6300SRichard Henderson } else { 23105dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 23115dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 23125dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 2313951c6300SRichard Henderson 23149e821eabSRichard Henderson /* arg = abcdefgh */ 23159e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull); 23169e821eabSRichard Henderson tcg_gen_shri_i64(t0, arg, 8); /* t0 = .abcdefg */ 23179e821eabSRichard Henderson tcg_gen_and_i64(t1, arg, t2); /* t1 = .b.d.f.h */ 23189e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = .a.c.e.g */ 23199e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 8); /* t1 = b.d.f.h. */ 23209e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = badcfehg */ 2321951c6300SRichard Henderson 23229e821eabSRichard Henderson tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull); 23239e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 16); /* t0 = ..badcfe */ 23249e821eabSRichard Henderson tcg_gen_and_i64(t1, ret, t2); /* t1 = ..dc..hg */ 23259e821eabSRichard Henderson tcg_gen_and_i64(t0, t0, t2); /* t0 = ..ba..fe */ 23269e821eabSRichard Henderson tcg_gen_shli_i64(t1, t1, 16); /* t1 = dc..hg.. */ 23279e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = dcbahgfe */ 2328951c6300SRichard Henderson 23299e821eabSRichard Henderson tcg_gen_shri_i64(t0, ret, 32); /* t0 = ....dcba */ 23309e821eabSRichard Henderson tcg_gen_shli_i64(t1, ret, 32); /* t1 = hgfe.... */ 23319e821eabSRichard Henderson tcg_gen_or_i64(ret, t0, t1); /* ret = hgfedcba */ 2332951c6300SRichard Henderson 2333951c6300SRichard Henderson tcg_temp_free_i64(t0); 2334951c6300SRichard Henderson tcg_temp_free_i64(t1); 23359e821eabSRichard Henderson tcg_temp_free_i64(t2); 2336951c6300SRichard Henderson } 2337951c6300SRichard Henderson } 2338951c6300SRichard Henderson 2339b8976aa5SPhilippe Mathieu-Daudé /* 2340b8976aa5SPhilippe Mathieu-Daudé * hswap_i64: Swap 16-bit halfwords within a 64-bit value. 2341b8976aa5SPhilippe Mathieu-Daudé * See also include/qemu/bitops.h, hswap64. 2342b8976aa5SPhilippe Mathieu-Daudé * 2343b8976aa5SPhilippe Mathieu-Daudé * Byte pattern: abcdefgh -> ghefcdab 2344b8976aa5SPhilippe Mathieu-Daudé */ 234546be8425SRichard Henderson void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg) 234646be8425SRichard Henderson { 234746be8425SRichard Henderson uint64_t m = 0x0000ffff0000ffffull; 23485dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 23495dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 235046be8425SRichard Henderson 2351b8976aa5SPhilippe Mathieu-Daudé /* arg = abcdefgh */ 2352b8976aa5SPhilippe Mathieu-Daudé tcg_gen_rotli_i64(t1, arg, 32); /* t1 = efghabcd */ 2353b8976aa5SPhilippe Mathieu-Daudé tcg_gen_andi_i64(t0, t1, m); /* t0 = ..gh..cd */ 2354b8976aa5SPhilippe Mathieu-Daudé tcg_gen_shli_i64(t0, t0, 16); /* t0 = gh..cd.. */ 2355b8976aa5SPhilippe Mathieu-Daudé tcg_gen_shri_i64(t1, t1, 16); /* t1 = ..efghab */ 2356b8976aa5SPhilippe Mathieu-Daudé tcg_gen_andi_i64(t1, t1, m); /* t1 = ..ef..ab */ 2357b8976aa5SPhilippe Mathieu-Daudé tcg_gen_or_i64(ret, t0, t1); /* ret = ghefcdab */ 235846be8425SRichard Henderson 235946be8425SRichard Henderson tcg_temp_free_i64(t0); 236046be8425SRichard Henderson tcg_temp_free_i64(t1); 236146be8425SRichard Henderson } 236246be8425SRichard Henderson 2363ad262fb5SPhilippe Mathieu-Daudé /* 2364ad262fb5SPhilippe Mathieu-Daudé * wswap_i64: Swap 32-bit words within a 64-bit value. 2365ad262fb5SPhilippe Mathieu-Daudé * 2366ad262fb5SPhilippe Mathieu-Daudé * Byte pattern: abcdefgh -> efghabcd 2367ad262fb5SPhilippe Mathieu-Daudé */ 236846be8425SRichard Henderson void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg) 236946be8425SRichard Henderson { 237046be8425SRichard Henderson /* Swapping 2 32-bit elements is a rotate. */ 237146be8425SRichard Henderson tcg_gen_rotli_i64(ret, arg, 32); 237246be8425SRichard Henderson } 237346be8425SRichard Henderson 2374951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg) 2375951c6300SRichard Henderson { 23763a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 23773a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 23783a13c3f3SRichard Henderson tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg)); 23793a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_not_i64) { 2380951c6300SRichard Henderson tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg); 2381951c6300SRichard Henderson } else { 2382951c6300SRichard Henderson tcg_gen_xori_i64(ret, arg, -1); 2383951c6300SRichard Henderson } 2384951c6300SRichard Henderson } 2385951c6300SRichard Henderson 2386951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2387951c6300SRichard Henderson { 23883a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 23893a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 23903a13c3f3SRichard Henderson tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 23913a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_andc_i64) { 2392951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2); 2393951c6300SRichard Henderson } else { 23945dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2395951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 2396951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, t0); 2397951c6300SRichard Henderson tcg_temp_free_i64(t0); 2398951c6300SRichard Henderson } 2399951c6300SRichard Henderson } 2400951c6300SRichard Henderson 2401951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2402951c6300SRichard Henderson { 24033a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 24043a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 24053a13c3f3SRichard Henderson tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 24063a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_eqv_i64) { 2407951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2); 2408951c6300SRichard Henderson } else { 2409951c6300SRichard Henderson tcg_gen_xor_i64(ret, arg1, arg2); 2410951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 2411951c6300SRichard Henderson } 2412951c6300SRichard Henderson } 2413951c6300SRichard Henderson 2414951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2415951c6300SRichard Henderson { 24163a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 24173a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 24183a13c3f3SRichard Henderson tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 24193a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nand_i64) { 2420951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2); 2421951c6300SRichard Henderson } else { 2422951c6300SRichard Henderson tcg_gen_and_i64(ret, arg1, arg2); 2423951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 2424951c6300SRichard Henderson } 2425951c6300SRichard Henderson } 2426951c6300SRichard Henderson 2427951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2428951c6300SRichard Henderson { 24293a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 24303a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 24313a13c3f3SRichard Henderson tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 24323a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_nor_i64) { 2433951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2); 2434951c6300SRichard Henderson } else { 2435951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, arg2); 2436951c6300SRichard Henderson tcg_gen_not_i64(ret, ret); 2437951c6300SRichard Henderson } 2438951c6300SRichard Henderson } 2439951c6300SRichard Henderson 2440951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2441951c6300SRichard Henderson { 24423a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 24433a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2)); 24443a13c3f3SRichard Henderson tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2)); 24453a13c3f3SRichard Henderson } else if (TCG_TARGET_HAS_orc_i64) { 2446951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2); 2447951c6300SRichard Henderson } else { 24485dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 2449951c6300SRichard Henderson tcg_gen_not_i64(t0, arg2); 2450951c6300SRichard Henderson tcg_gen_or_i64(ret, arg1, t0); 2451951c6300SRichard Henderson tcg_temp_free_i64(t0); 2452951c6300SRichard Henderson } 2453951c6300SRichard Henderson } 2454951c6300SRichard Henderson 24550e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 24560e28d006SRichard Henderson { 24570e28d006SRichard Henderson if (TCG_TARGET_HAS_clz_i64) { 24580e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2); 24590e28d006SRichard Henderson } else { 24600e28d006SRichard Henderson gen_helper_clz_i64(ret, arg1, arg2); 24610e28d006SRichard Henderson } 24620e28d006SRichard Henderson } 24630e28d006SRichard Henderson 24640e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 24650e28d006SRichard Henderson { 24660e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 24670e28d006SRichard Henderson && TCG_TARGET_HAS_clz_i32 24680e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 24695dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 247011d11d61SRichard Henderson tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32); 24710e28d006SRichard Henderson tcg_gen_addi_i32(t, t, 32); 24720e28d006SRichard Henderson tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t); 24730e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 24740e28d006SRichard Henderson tcg_temp_free_i32(t); 24750e28d006SRichard Henderson } else { 2476f04de891SRichard Henderson tcg_gen_clz_i64(ret, arg1, tcg_constant_i64(arg2)); 24770e28d006SRichard Henderson } 24780e28d006SRichard Henderson } 24790e28d006SRichard Henderson 24800e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 24810e28d006SRichard Henderson { 24820e28d006SRichard Henderson if (TCG_TARGET_HAS_ctz_i64) { 24830e28d006SRichard Henderson tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2); 248414e99210SRichard Henderson } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) { 24855dd48602SRichard Henderson TCGv_i64 z, t = tcg_temp_ebb_new_i64(); 248614e99210SRichard Henderson 248714e99210SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 248814e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 248914e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 249014e99210SRichard Henderson tcg_gen_ctpop_i64(t, t); 249114e99210SRichard Henderson } else { 249214e99210SRichard Henderson /* Since all non-x86 hosts have clz(0) == 64, don't fight it. */ 249314e99210SRichard Henderson tcg_gen_neg_i64(t, arg1); 249414e99210SRichard Henderson tcg_gen_and_i64(t, t, arg1); 249514e99210SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 249614e99210SRichard Henderson tcg_gen_xori_i64(t, t, 63); 249714e99210SRichard Henderson } 249811d11d61SRichard Henderson z = tcg_constant_i64(0); 249914e99210SRichard Henderson tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t); 250014e99210SRichard Henderson tcg_temp_free_i64(t); 250114e99210SRichard Henderson tcg_temp_free_i64(z); 25020e28d006SRichard Henderson } else { 25030e28d006SRichard Henderson gen_helper_ctz_i64(ret, arg1, arg2); 25040e28d006SRichard Henderson } 25050e28d006SRichard Henderson } 25060e28d006SRichard Henderson 25070e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) 25080e28d006SRichard Henderson { 25090e28d006SRichard Henderson if (TCG_TARGET_REG_BITS == 32 25100e28d006SRichard Henderson && TCG_TARGET_HAS_ctz_i32 25110e28d006SRichard Henderson && arg2 <= 0xffffffffu) { 25125dd48602SRichard Henderson TCGv_i32 t32 = tcg_temp_ebb_new_i32(); 251311d11d61SRichard Henderson tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32); 25140e28d006SRichard Henderson tcg_gen_addi_i32(t32, t32, 32); 25150e28d006SRichard Henderson tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32); 25160e28d006SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 25170e28d006SRichard Henderson tcg_temp_free_i32(t32); 251814e99210SRichard Henderson } else if (!TCG_TARGET_HAS_ctz_i64 251914e99210SRichard Henderson && TCG_TARGET_HAS_ctpop_i64 252014e99210SRichard Henderson && arg2 == 64) { 252114e99210SRichard Henderson /* This equivalence has the advantage of not requiring a fixup. */ 25225dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 252314e99210SRichard Henderson tcg_gen_subi_i64(t, arg1, 1); 252414e99210SRichard Henderson tcg_gen_andc_i64(t, t, arg1); 252514e99210SRichard Henderson tcg_gen_ctpop_i64(ret, t); 252614e99210SRichard Henderson tcg_temp_free_i64(t); 25270e28d006SRichard Henderson } else { 2528f04de891SRichard Henderson tcg_gen_ctz_i64(ret, arg1, tcg_constant_i64(arg2)); 25290e28d006SRichard Henderson } 25300e28d006SRichard Henderson } 25310e28d006SRichard Henderson 2532086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg) 2533086920c2SRichard Henderson { 2534086920c2SRichard Henderson if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) { 25355dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 2536086920c2SRichard Henderson tcg_gen_sari_i64(t, arg, 63); 2537086920c2SRichard Henderson tcg_gen_xor_i64(t, t, arg); 2538086920c2SRichard Henderson tcg_gen_clzi_i64(t, t, 64); 2539086920c2SRichard Henderson tcg_gen_subi_i64(ret, t, 1); 2540086920c2SRichard Henderson tcg_temp_free_i64(t); 2541086920c2SRichard Henderson } else { 2542086920c2SRichard Henderson gen_helper_clrsb_i64(ret, arg); 2543086920c2SRichard Henderson } 2544086920c2SRichard Henderson } 2545086920c2SRichard Henderson 2546a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1) 2547a768e4e9SRichard Henderson { 2548a768e4e9SRichard Henderson if (TCG_TARGET_HAS_ctpop_i64) { 2549a768e4e9SRichard Henderson tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1); 2550a768e4e9SRichard Henderson } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) { 2551a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2552a768e4e9SRichard Henderson tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2553a768e4e9SRichard Henderson tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret)); 2554a768e4e9SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 2555a768e4e9SRichard Henderson } else { 2556a768e4e9SRichard Henderson gen_helper_ctpop_i64(ret, arg1); 2557a768e4e9SRichard Henderson } 2558a768e4e9SRichard Henderson } 2559a768e4e9SRichard Henderson 2560951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2561951c6300SRichard Henderson { 2562951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 2563951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2); 2564951c6300SRichard Henderson } else { 2565951c6300SRichard Henderson TCGv_i64 t0, t1; 25665dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 25675dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2568951c6300SRichard Henderson tcg_gen_shl_i64(t0, arg1, arg2); 2569951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 2570951c6300SRichard Henderson tcg_gen_shr_i64(t1, arg1, t1); 2571951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2572951c6300SRichard Henderson tcg_temp_free_i64(t0); 2573951c6300SRichard Henderson tcg_temp_free_i64(t1); 2574951c6300SRichard Henderson } 2575951c6300SRichard Henderson } 2576951c6300SRichard Henderson 257707dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2578951c6300SRichard Henderson { 257907dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2580951c6300SRichard Henderson /* some cases can be optimized here */ 2581951c6300SRichard Henderson if (arg2 == 0) { 2582951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 2583951c6300SRichard Henderson } else if (TCG_TARGET_HAS_rot_i64) { 258411d11d61SRichard Henderson tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2)); 2585951c6300SRichard Henderson } else { 2586951c6300SRichard Henderson TCGv_i64 t0, t1; 25875dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 25885dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2589951c6300SRichard Henderson tcg_gen_shli_i64(t0, arg1, arg2); 2590951c6300SRichard Henderson tcg_gen_shri_i64(t1, arg1, 64 - arg2); 2591951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2592951c6300SRichard Henderson tcg_temp_free_i64(t0); 2593951c6300SRichard Henderson tcg_temp_free_i64(t1); 2594951c6300SRichard Henderson } 2595951c6300SRichard Henderson } 2596951c6300SRichard Henderson 2597951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) 2598951c6300SRichard Henderson { 2599951c6300SRichard Henderson if (TCG_TARGET_HAS_rot_i64) { 2600951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2); 2601951c6300SRichard Henderson } else { 2602951c6300SRichard Henderson TCGv_i64 t0, t1; 26035dd48602SRichard Henderson t0 = tcg_temp_ebb_new_i64(); 26045dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2605951c6300SRichard Henderson tcg_gen_shr_i64(t0, arg1, arg2); 2606951c6300SRichard Henderson tcg_gen_subfi_i64(t1, 64, arg2); 2607951c6300SRichard Henderson tcg_gen_shl_i64(t1, arg1, t1); 2608951c6300SRichard Henderson tcg_gen_or_i64(ret, t0, t1); 2609951c6300SRichard Henderson tcg_temp_free_i64(t0); 2610951c6300SRichard Henderson tcg_temp_free_i64(t1); 2611951c6300SRichard Henderson } 2612951c6300SRichard Henderson } 2613951c6300SRichard Henderson 261407dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) 2615951c6300SRichard Henderson { 261607dada03SRichard Henderson tcg_debug_assert(arg2 >= 0 && arg2 < 64); 2617951c6300SRichard Henderson /* some cases can be optimized here */ 2618951c6300SRichard Henderson if (arg2 == 0) { 2619951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg1); 2620951c6300SRichard Henderson } else { 2621951c6300SRichard Henderson tcg_gen_rotli_i64(ret, arg1, 64 - arg2); 2622951c6300SRichard Henderson } 2623951c6300SRichard Henderson } 2624951c6300SRichard Henderson 2625951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, 2626951c6300SRichard Henderson unsigned int ofs, unsigned int len) 2627951c6300SRichard Henderson { 2628951c6300SRichard Henderson uint64_t mask; 2629951c6300SRichard Henderson TCGv_i64 t1; 2630951c6300SRichard Henderson 2631951c6300SRichard Henderson tcg_debug_assert(ofs < 64); 26320d0d309dSRichard Henderson tcg_debug_assert(len > 0); 2633951c6300SRichard Henderson tcg_debug_assert(len <= 64); 2634951c6300SRichard Henderson tcg_debug_assert(ofs + len <= 64); 2635951c6300SRichard Henderson 26360d0d309dSRichard Henderson if (len == 64) { 2637951c6300SRichard Henderson tcg_gen_mov_i64(ret, arg2); 2638951c6300SRichard Henderson return; 2639951c6300SRichard Henderson } 2640951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) { 2641951c6300SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); 2642951c6300SRichard Henderson return; 2643951c6300SRichard Henderson } 2644951c6300SRichard Henderson 26453a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 2646951c6300SRichard Henderson if (ofs >= 32) { 2647951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 2648951c6300SRichard Henderson TCGV_LOW(arg2), ofs - 32, len); 2649951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 2650951c6300SRichard Henderson return; 2651951c6300SRichard Henderson } 2652951c6300SRichard Henderson if (ofs + len <= 32) { 2653951c6300SRichard Henderson tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1), 2654951c6300SRichard Henderson TCGV_LOW(arg2), ofs, len); 2655951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 2656951c6300SRichard Henderson return; 2657951c6300SRichard Henderson } 26583a13c3f3SRichard Henderson } 2659951c6300SRichard Henderson 26605dd48602SRichard Henderson t1 = tcg_temp_ebb_new_i64(); 2661951c6300SRichard Henderson 2662b0a60567SRichard Henderson if (TCG_TARGET_HAS_extract2_i64) { 2663b0a60567SRichard Henderson if (ofs + len == 64) { 2664b0a60567SRichard Henderson tcg_gen_shli_i64(t1, arg1, len); 2665b0a60567SRichard Henderson tcg_gen_extract2_i64(ret, t1, arg2, len); 2666b0a60567SRichard Henderson goto done; 2667b0a60567SRichard Henderson } 2668b0a60567SRichard Henderson if (ofs == 0) { 2669b0a60567SRichard Henderson tcg_gen_extract2_i64(ret, arg1, arg2, len); 2670b0a60567SRichard Henderson tcg_gen_rotli_i64(ret, ret, len); 2671b0a60567SRichard Henderson goto done; 2672b0a60567SRichard Henderson } 2673b0a60567SRichard Henderson } 2674b0a60567SRichard Henderson 2675b0a60567SRichard Henderson mask = (1ull << len) - 1; 2676951c6300SRichard Henderson if (ofs + len < 64) { 2677951c6300SRichard Henderson tcg_gen_andi_i64(t1, arg2, mask); 2678951c6300SRichard Henderson tcg_gen_shli_i64(t1, t1, ofs); 2679951c6300SRichard Henderson } else { 2680951c6300SRichard Henderson tcg_gen_shli_i64(t1, arg2, ofs); 2681951c6300SRichard Henderson } 2682951c6300SRichard Henderson tcg_gen_andi_i64(ret, arg1, ~(mask << ofs)); 2683951c6300SRichard Henderson tcg_gen_or_i64(ret, ret, t1); 2684b0a60567SRichard Henderson done: 2685951c6300SRichard Henderson tcg_temp_free_i64(t1); 2686951c6300SRichard Henderson } 2687951c6300SRichard Henderson 268807cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, 268907cc68d5SRichard Henderson unsigned int ofs, unsigned int len) 269007cc68d5SRichard Henderson { 269107cc68d5SRichard Henderson tcg_debug_assert(ofs < 64); 269207cc68d5SRichard Henderson tcg_debug_assert(len > 0); 269307cc68d5SRichard Henderson tcg_debug_assert(len <= 64); 269407cc68d5SRichard Henderson tcg_debug_assert(ofs + len <= 64); 269507cc68d5SRichard Henderson 269607cc68d5SRichard Henderson if (ofs + len == 64) { 269707cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 269807cc68d5SRichard Henderson } else if (ofs == 0) { 269907cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 270007cc68d5SRichard Henderson } else if (TCG_TARGET_HAS_deposit_i64 270107cc68d5SRichard Henderson && TCG_TARGET_deposit_i64_valid(ofs, len)) { 270211d11d61SRichard Henderson TCGv_i64 zero = tcg_constant_i64(0); 270307cc68d5SRichard Henderson tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); 270407cc68d5SRichard Henderson } else { 270507cc68d5SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 270607cc68d5SRichard Henderson if (ofs >= 32) { 270707cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg), 270807cc68d5SRichard Henderson ofs - 32, len); 270907cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_LOW(ret), 0); 271007cc68d5SRichard Henderson return; 271107cc68d5SRichard Henderson } 271207cc68d5SRichard Henderson if (ofs + len <= 32) { 271307cc68d5SRichard Henderson tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 271407cc68d5SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 271507cc68d5SRichard Henderson return; 271607cc68d5SRichard Henderson } 271707cc68d5SRichard Henderson } 271807cc68d5SRichard Henderson /* To help two-operand hosts we prefer to zero-extend first, 271907cc68d5SRichard Henderson which allows ARG to stay live. */ 272007cc68d5SRichard Henderson switch (len) { 272107cc68d5SRichard Henderson case 32: 272207cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 272307cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 272407cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 272507cc68d5SRichard Henderson return; 272607cc68d5SRichard Henderson } 272707cc68d5SRichard Henderson break; 272807cc68d5SRichard Henderson case 16: 272907cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 273007cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 273107cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 273207cc68d5SRichard Henderson return; 273307cc68d5SRichard Henderson } 273407cc68d5SRichard Henderson break; 273507cc68d5SRichard Henderson case 8: 273607cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 273707cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 273807cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 273907cc68d5SRichard Henderson return; 274007cc68d5SRichard Henderson } 274107cc68d5SRichard Henderson break; 274207cc68d5SRichard Henderson } 274307cc68d5SRichard Henderson /* Otherwise prefer zero-extension over AND for code size. */ 274407cc68d5SRichard Henderson switch (ofs + len) { 274507cc68d5SRichard Henderson case 32: 274607cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 274707cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 274807cc68d5SRichard Henderson tcg_gen_ext32u_i64(ret, ret); 274907cc68d5SRichard Henderson return; 275007cc68d5SRichard Henderson } 275107cc68d5SRichard Henderson break; 275207cc68d5SRichard Henderson case 16: 275307cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 275407cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 275507cc68d5SRichard Henderson tcg_gen_ext16u_i64(ret, ret); 275607cc68d5SRichard Henderson return; 275707cc68d5SRichard Henderson } 275807cc68d5SRichard Henderson break; 275907cc68d5SRichard Henderson case 8: 276007cc68d5SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 276107cc68d5SRichard Henderson tcg_gen_shli_i64(ret, arg, ofs); 276207cc68d5SRichard Henderson tcg_gen_ext8u_i64(ret, ret); 276307cc68d5SRichard Henderson return; 276407cc68d5SRichard Henderson } 276507cc68d5SRichard Henderson break; 276607cc68d5SRichard Henderson } 276707cc68d5SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 276807cc68d5SRichard Henderson tcg_gen_shli_i64(ret, ret, ofs); 276907cc68d5SRichard Henderson } 277007cc68d5SRichard Henderson } 277107cc68d5SRichard Henderson 27727ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, 27737ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 27747ec8bab3SRichard Henderson { 27757ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 27767ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 27777ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 27787ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 27797ec8bab3SRichard Henderson 27807ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if extract is supported. */ 27817ec8bab3SRichard Henderson if (ofs + len == 64) { 27827ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, 64 - len); 27837ec8bab3SRichard Henderson return; 27847ec8bab3SRichard Henderson } 27857ec8bab3SRichard Henderson if (ofs == 0) { 27867ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); 27877ec8bab3SRichard Henderson return; 27887ec8bab3SRichard Henderson } 27897ec8bab3SRichard Henderson 27907ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 27917ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 27927ec8bab3SRichard Henderson if (ofs >= 32) { 27937ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 27947ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 27957ec8bab3SRichard Henderson return; 27967ec8bab3SRichard Henderson } 27977ec8bab3SRichard Henderson if (ofs + len <= 32) { 27987ec8bab3SRichard Henderson tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 27997ec8bab3SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 28007ec8bab3SRichard Henderson return; 28017ec8bab3SRichard Henderson } 28027ec8bab3SRichard Henderson /* The field is split across two words. One double-word 28037ec8bab3SRichard Henderson shift is better than two double-word shifts. */ 28047ec8bab3SRichard Henderson goto do_shift_and; 28057ec8bab3SRichard Henderson } 28067ec8bab3SRichard Henderson 28077ec8bab3SRichard Henderson if (TCG_TARGET_HAS_extract_i64 28087ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 28097ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len); 28107ec8bab3SRichard Henderson return; 28117ec8bab3SRichard Henderson } 28127ec8bab3SRichard Henderson 28137ec8bab3SRichard Henderson /* Assume that zero-extension, if available, is cheaper than a shift. */ 28147ec8bab3SRichard Henderson switch (ofs + len) { 28157ec8bab3SRichard Henderson case 32: 28167ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32u_i64) { 28177ec8bab3SRichard Henderson tcg_gen_ext32u_i64(ret, arg); 28187ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 28197ec8bab3SRichard Henderson return; 28207ec8bab3SRichard Henderson } 28217ec8bab3SRichard Henderson break; 28227ec8bab3SRichard Henderson case 16: 28237ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16u_i64) { 28247ec8bab3SRichard Henderson tcg_gen_ext16u_i64(ret, arg); 28257ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 28267ec8bab3SRichard Henderson return; 28277ec8bab3SRichard Henderson } 28287ec8bab3SRichard Henderson break; 28297ec8bab3SRichard Henderson case 8: 28307ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8u_i64) { 28317ec8bab3SRichard Henderson tcg_gen_ext8u_i64(ret, arg); 28327ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, ofs); 28337ec8bab3SRichard Henderson return; 28347ec8bab3SRichard Henderson } 28357ec8bab3SRichard Henderson break; 28367ec8bab3SRichard Henderson } 28377ec8bab3SRichard Henderson 28387ec8bab3SRichard Henderson /* ??? Ideally we'd know what values are available for immediate AND. 28397ec8bab3SRichard Henderson Assume that 8 bits are available, plus the special cases of 16 and 32, 28407ec8bab3SRichard Henderson so that we get ext8u, ext16u, and ext32u. */ 28417ec8bab3SRichard Henderson switch (len) { 28427ec8bab3SRichard Henderson case 1 ... 8: case 16: case 32: 28437ec8bab3SRichard Henderson do_shift_and: 28447ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 28457ec8bab3SRichard Henderson tcg_gen_andi_i64(ret, ret, (1ull << len) - 1); 28467ec8bab3SRichard Henderson break; 28477ec8bab3SRichard Henderson default: 28487ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 28497ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, ret, 64 - len); 28507ec8bab3SRichard Henderson break; 28517ec8bab3SRichard Henderson } 28527ec8bab3SRichard Henderson } 28537ec8bab3SRichard Henderson 28547ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg, 28557ec8bab3SRichard Henderson unsigned int ofs, unsigned int len) 28567ec8bab3SRichard Henderson { 28577ec8bab3SRichard Henderson tcg_debug_assert(ofs < 64); 28587ec8bab3SRichard Henderson tcg_debug_assert(len > 0); 28597ec8bab3SRichard Henderson tcg_debug_assert(len <= 64); 28607ec8bab3SRichard Henderson tcg_debug_assert(ofs + len <= 64); 28617ec8bab3SRichard Henderson 28627ec8bab3SRichard Henderson /* Canonicalize certain special cases, even if sextract is supported. */ 28637ec8bab3SRichard Henderson if (ofs + len == 64) { 28647ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, arg, 64 - len); 28657ec8bab3SRichard Henderson return; 28667ec8bab3SRichard Henderson } 28677ec8bab3SRichard Henderson if (ofs == 0) { 28687ec8bab3SRichard Henderson switch (len) { 28697ec8bab3SRichard Henderson case 32: 28707ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 28717ec8bab3SRichard Henderson return; 28727ec8bab3SRichard Henderson case 16: 28737ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 28747ec8bab3SRichard Henderson return; 28757ec8bab3SRichard Henderson case 8: 28767ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 28777ec8bab3SRichard Henderson return; 28787ec8bab3SRichard Henderson } 28797ec8bab3SRichard Henderson } 28807ec8bab3SRichard Henderson 28817ec8bab3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 28827ec8bab3SRichard Henderson /* Look for a 32-bit extract within one of the two words. */ 28837ec8bab3SRichard Henderson if (ofs >= 32) { 28847ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len); 28857ec8bab3SRichard Henderson } else if (ofs + len <= 32) { 28867ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); 28877ec8bab3SRichard Henderson } else if (ofs == 0) { 28887ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg)); 28897ec8bab3SRichard Henderson tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32); 28907ec8bab3SRichard Henderson return; 28917ec8bab3SRichard Henderson } else if (len > 32) { 28925dd48602SRichard Henderson TCGv_i32 t = tcg_temp_ebb_new_i32(); 28937ec8bab3SRichard Henderson /* Extract the bits for the high word normally. */ 28947ec8bab3SRichard Henderson tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32); 28957ec8bab3SRichard Henderson /* Shift the field down for the low part. */ 28967ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 28977ec8bab3SRichard Henderson /* Overwrite the shift into the high part. */ 28987ec8bab3SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(ret), t); 28997ec8bab3SRichard Henderson tcg_temp_free_i32(t); 29007ec8bab3SRichard Henderson return; 29017ec8bab3SRichard Henderson } else { 29027ec8bab3SRichard Henderson /* Shift the field down for the low part, such that the 29037ec8bab3SRichard Henderson field sits at the MSB. */ 29047ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs + len - 32); 29057ec8bab3SRichard Henderson /* Shift the field down from the MSB, sign extending. */ 29067ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len); 29077ec8bab3SRichard Henderson } 29087ec8bab3SRichard Henderson /* Sign-extend the field from 32 bits. */ 29097ec8bab3SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 29107ec8bab3SRichard Henderson return; 29117ec8bab3SRichard Henderson } 29127ec8bab3SRichard Henderson 29137ec8bab3SRichard Henderson if (TCG_TARGET_HAS_sextract_i64 29147ec8bab3SRichard Henderson && TCG_TARGET_extract_i64_valid(ofs, len)) { 29157ec8bab3SRichard Henderson tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); 29167ec8bab3SRichard Henderson return; 29177ec8bab3SRichard Henderson } 29187ec8bab3SRichard Henderson 29197ec8bab3SRichard Henderson /* Assume that sign-extension, if available, is cheaper than a shift. */ 29207ec8bab3SRichard Henderson switch (ofs + len) { 29217ec8bab3SRichard Henderson case 32: 29227ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 29237ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, arg); 29247ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 29257ec8bab3SRichard Henderson return; 29267ec8bab3SRichard Henderson } 29277ec8bab3SRichard Henderson break; 29287ec8bab3SRichard Henderson case 16: 29297ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 29307ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, arg); 29317ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 29327ec8bab3SRichard Henderson return; 29337ec8bab3SRichard Henderson } 29347ec8bab3SRichard Henderson break; 29357ec8bab3SRichard Henderson case 8: 29367ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 29377ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, arg); 29387ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, ofs); 29397ec8bab3SRichard Henderson return; 29407ec8bab3SRichard Henderson } 29417ec8bab3SRichard Henderson break; 29427ec8bab3SRichard Henderson } 29437ec8bab3SRichard Henderson switch (len) { 29447ec8bab3SRichard Henderson case 32: 29457ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext32s_i64) { 29467ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 29477ec8bab3SRichard Henderson tcg_gen_ext32s_i64(ret, ret); 29487ec8bab3SRichard Henderson return; 29497ec8bab3SRichard Henderson } 29507ec8bab3SRichard Henderson break; 29517ec8bab3SRichard Henderson case 16: 29527ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext16s_i64) { 29537ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 29547ec8bab3SRichard Henderson tcg_gen_ext16s_i64(ret, ret); 29557ec8bab3SRichard Henderson return; 29567ec8bab3SRichard Henderson } 29577ec8bab3SRichard Henderson break; 29587ec8bab3SRichard Henderson case 8: 29597ec8bab3SRichard Henderson if (TCG_TARGET_HAS_ext8s_i64) { 29607ec8bab3SRichard Henderson tcg_gen_shri_i64(ret, arg, ofs); 29617ec8bab3SRichard Henderson tcg_gen_ext8s_i64(ret, ret); 29627ec8bab3SRichard Henderson return; 29637ec8bab3SRichard Henderson } 29647ec8bab3SRichard Henderson break; 29657ec8bab3SRichard Henderson } 29667ec8bab3SRichard Henderson tcg_gen_shli_i64(ret, arg, 64 - len - ofs); 29677ec8bab3SRichard Henderson tcg_gen_sari_i64(ret, ret, 64 - len); 29687ec8bab3SRichard Henderson } 29697ec8bab3SRichard Henderson 29702089fcc9SDavid Hildenbrand /* 29712089fcc9SDavid Hildenbrand * Extract 64 bits from a 128-bit input, ah:al, starting from ofs. 29722089fcc9SDavid Hildenbrand * Unlike tcg_gen_extract_i64 above, len is fixed at 64. 29732089fcc9SDavid Hildenbrand */ 29742089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah, 29752089fcc9SDavid Hildenbrand unsigned int ofs) 29762089fcc9SDavid Hildenbrand { 29772089fcc9SDavid Hildenbrand tcg_debug_assert(ofs <= 64); 29782089fcc9SDavid Hildenbrand if (ofs == 0) { 29792089fcc9SDavid Hildenbrand tcg_gen_mov_i64(ret, al); 29802089fcc9SDavid Hildenbrand } else if (ofs == 64) { 29812089fcc9SDavid Hildenbrand tcg_gen_mov_i64(ret, ah); 29822089fcc9SDavid Hildenbrand } else if (al == ah) { 29832089fcc9SDavid Hildenbrand tcg_gen_rotri_i64(ret, al, ofs); 2984fce1296fSRichard Henderson } else if (TCG_TARGET_HAS_extract2_i64) { 2985fce1296fSRichard Henderson tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs); 29862089fcc9SDavid Hildenbrand } else { 29875dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 29882089fcc9SDavid Hildenbrand tcg_gen_shri_i64(t0, al, ofs); 29892089fcc9SDavid Hildenbrand tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs); 29902089fcc9SDavid Hildenbrand tcg_temp_free_i64(t0); 29912089fcc9SDavid Hildenbrand } 29922089fcc9SDavid Hildenbrand } 29932089fcc9SDavid Hildenbrand 2994951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, 2995951c6300SRichard Henderson TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2) 2996951c6300SRichard Henderson { 299737ed3bf1SRichard Henderson if (cond == TCG_COND_ALWAYS) { 299837ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v1); 299937ed3bf1SRichard Henderson } else if (cond == TCG_COND_NEVER) { 300037ed3bf1SRichard Henderson tcg_gen_mov_i64(ret, v2); 30013871be75SRichard Henderson } else if (TCG_TARGET_REG_BITS == 64) { 30023871be75SRichard Henderson tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); 30033871be75SRichard Henderson } else { 30045dd48602SRichard Henderson TCGv_i32 t0 = tcg_temp_ebb_new_i32(); 30053871be75SRichard Henderson TCGv_i32 zero = tcg_constant_i32(0); 30063871be75SRichard Henderson 3007951c6300SRichard Henderson tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, 3008951c6300SRichard Henderson TCGV_LOW(c1), TCGV_HIGH(c1), 3009951c6300SRichard Henderson TCGV_LOW(c2), TCGV_HIGH(c2), cond); 3010951c6300SRichard Henderson 30113871be75SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, zero, 3012951c6300SRichard Henderson TCGV_LOW(v1), TCGV_LOW(v2)); 30133871be75SRichard Henderson tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, zero, 3014951c6300SRichard Henderson TCGV_HIGH(v1), TCGV_HIGH(v2)); 3015951c6300SRichard Henderson 3016951c6300SRichard Henderson tcg_temp_free_i32(t0); 3017951c6300SRichard Henderson } 3018951c6300SRichard Henderson } 3019951c6300SRichard Henderson 3020951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 3021951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 3022951c6300SRichard Henderson { 3023951c6300SRichard Henderson if (TCG_TARGET_HAS_add2_i64) { 3024951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh); 3025951c6300SRichard Henderson } else { 30265dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 30275dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 3028951c6300SRichard Henderson tcg_gen_add_i64(t0, al, bl); 3029951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al); 3030951c6300SRichard Henderson tcg_gen_add_i64(rh, ah, bh); 3031951c6300SRichard Henderson tcg_gen_add_i64(rh, rh, t1); 3032951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 3033951c6300SRichard Henderson tcg_temp_free_i64(t0); 3034951c6300SRichard Henderson tcg_temp_free_i64(t1); 3035951c6300SRichard Henderson } 3036951c6300SRichard Henderson } 3037951c6300SRichard Henderson 3038951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, 3039951c6300SRichard Henderson TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) 3040951c6300SRichard Henderson { 3041951c6300SRichard Henderson if (TCG_TARGET_HAS_sub2_i64) { 3042951c6300SRichard Henderson tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh); 3043951c6300SRichard Henderson } else { 30445dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 30455dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 3046951c6300SRichard Henderson tcg_gen_sub_i64(t0, al, bl); 3047951c6300SRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl); 3048951c6300SRichard Henderson tcg_gen_sub_i64(rh, ah, bh); 3049951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t1); 3050951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 3051951c6300SRichard Henderson tcg_temp_free_i64(t0); 3052951c6300SRichard Henderson tcg_temp_free_i64(t1); 3053951c6300SRichard Henderson } 3054951c6300SRichard Henderson } 3055951c6300SRichard Henderson 3056951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 3057951c6300SRichard Henderson { 3058951c6300SRichard Henderson if (TCG_TARGET_HAS_mulu2_i64) { 3059951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); 3060951c6300SRichard Henderson } else if (TCG_TARGET_HAS_muluh_i64) { 30615dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 3062951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 3063951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2); 3064951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 3065951c6300SRichard Henderson tcg_temp_free_i64(t); 3066951c6300SRichard Henderson } else { 30675dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 3068951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 3069951c6300SRichard Henderson gen_helper_muluh_i64(rh, arg1, arg2); 3070951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 3071951c6300SRichard Henderson tcg_temp_free_i64(t0); 3072951c6300SRichard Henderson } 3073951c6300SRichard Henderson } 3074951c6300SRichard Henderson 3075951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 3076951c6300SRichard Henderson { 3077951c6300SRichard Henderson if (TCG_TARGET_HAS_muls2_i64) { 3078951c6300SRichard Henderson tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); 3079951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulsh_i64) { 30805dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 3081951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); 3082951c6300SRichard Henderson tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2); 3083951c6300SRichard Henderson tcg_gen_mov_i64(rl, t); 3084951c6300SRichard Henderson tcg_temp_free_i64(t); 3085951c6300SRichard Henderson } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) { 30865dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 30875dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 30885dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 30895dd48602SRichard Henderson TCGv_i64 t3 = tcg_temp_ebb_new_i64(); 3090951c6300SRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 3091951c6300SRichard Henderson /* Adjust for negative inputs. */ 3092951c6300SRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 3093951c6300SRichard Henderson tcg_gen_sari_i64(t3, arg2, 63); 3094951c6300SRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 3095951c6300SRichard Henderson tcg_gen_and_i64(t3, t3, arg1); 3096951c6300SRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 3097951c6300SRichard Henderson tcg_gen_sub_i64(rh, rh, t3); 3098951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 3099951c6300SRichard Henderson tcg_temp_free_i64(t0); 3100951c6300SRichard Henderson tcg_temp_free_i64(t1); 3101951c6300SRichard Henderson tcg_temp_free_i64(t2); 3102951c6300SRichard Henderson tcg_temp_free_i64(t3); 3103951c6300SRichard Henderson } else { 31045dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 3105951c6300SRichard Henderson tcg_gen_mul_i64(t0, arg1, arg2); 3106951c6300SRichard Henderson gen_helper_mulsh_i64(rh, arg1, arg2); 3107951c6300SRichard Henderson tcg_gen_mov_i64(rl, t0); 3108951c6300SRichard Henderson tcg_temp_free_i64(t0); 3109951c6300SRichard Henderson } 3110951c6300SRichard Henderson } 3111951c6300SRichard Henderson 31125087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) 31135087abfbSRichard Henderson { 31145dd48602SRichard Henderson TCGv_i64 t0 = tcg_temp_ebb_new_i64(); 31155dd48602SRichard Henderson TCGv_i64 t1 = tcg_temp_ebb_new_i64(); 31165dd48602SRichard Henderson TCGv_i64 t2 = tcg_temp_ebb_new_i64(); 31175087abfbSRichard Henderson tcg_gen_mulu2_i64(t0, t1, arg1, arg2); 31185087abfbSRichard Henderson /* Adjust for negative input for the signed arg1. */ 31195087abfbSRichard Henderson tcg_gen_sari_i64(t2, arg1, 63); 31205087abfbSRichard Henderson tcg_gen_and_i64(t2, t2, arg2); 31215087abfbSRichard Henderson tcg_gen_sub_i64(rh, t1, t2); 31225087abfbSRichard Henderson tcg_gen_mov_i64(rl, t0); 31235087abfbSRichard Henderson tcg_temp_free_i64(t0); 31245087abfbSRichard Henderson tcg_temp_free_i64(t1); 31255087abfbSRichard Henderson tcg_temp_free_i64(t2); 31265087abfbSRichard Henderson } 31275087abfbSRichard Henderson 3128b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 3129b87fb8cdSRichard Henderson { 3130b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); 3131b87fb8cdSRichard Henderson } 3132b87fb8cdSRichard Henderson 3133b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 3134b87fb8cdSRichard Henderson { 3135b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); 3136b87fb8cdSRichard Henderson } 3137b87fb8cdSRichard Henderson 3138b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 3139b87fb8cdSRichard Henderson { 3140b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); 3141b87fb8cdSRichard Henderson } 3142b87fb8cdSRichard Henderson 3143b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) 3144b87fb8cdSRichard Henderson { 3145b87fb8cdSRichard Henderson tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); 3146b87fb8cdSRichard Henderson } 3147b87fb8cdSRichard Henderson 3148ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a) 3149ff1f11f7SRichard Henderson { 31505dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 3151ff1f11f7SRichard Henderson 3152ff1f11f7SRichard Henderson tcg_gen_sari_i64(t, a, 63); 3153ff1f11f7SRichard Henderson tcg_gen_xor_i64(ret, a, t); 3154ff1f11f7SRichard Henderson tcg_gen_sub_i64(ret, ret, t); 3155ff1f11f7SRichard Henderson tcg_temp_free_i64(t); 3156ff1f11f7SRichard Henderson } 3157ff1f11f7SRichard Henderson 3158951c6300SRichard Henderson /* Size changing operations. */ 3159951c6300SRichard Henderson 3160609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 3161951c6300SRichard Henderson { 31623a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 3163951c6300SRichard Henderson tcg_gen_mov_i32(ret, TCGV_LOW(arg)); 316413d885b0SRichard Henderson } else if (TCG_TARGET_HAS_extr_i64_i32) { 3165b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrl_i64_i32, 3166ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 3167951c6300SRichard Henderson } else { 3168dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)arg); 3169609ad705SRichard Henderson } 3170609ad705SRichard Henderson } 3171609ad705SRichard Henderson 3172609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg) 3173609ad705SRichard Henderson { 3174609ad705SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 3175609ad705SRichard Henderson tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); 317613d885b0SRichard Henderson } else if (TCG_TARGET_HAS_extr_i64_i32) { 3177b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extrh_i64_i32, 3178ae8b75dcSRichard Henderson tcgv_i32_arg(ret), tcgv_i64_arg(arg)); 3179951c6300SRichard Henderson } else { 31805dd48602SRichard Henderson TCGv_i64 t = tcg_temp_ebb_new_i64(); 3181609ad705SRichard Henderson tcg_gen_shri_i64(t, arg, 32); 3182dc41aa7dSRichard Henderson tcg_gen_mov_i32(ret, (TCGv_i32)t); 3183951c6300SRichard Henderson tcg_temp_free_i64(t); 3184951c6300SRichard Henderson } 3185951c6300SRichard Henderson } 3186951c6300SRichard Henderson 3187951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 3188951c6300SRichard Henderson { 31893a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 3190951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 3191951c6300SRichard Henderson tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 31923a13c3f3SRichard Henderson } else { 3193b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_extu_i32_i64, 3194ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 31953a13c3f3SRichard Henderson } 3196951c6300SRichard Henderson } 3197951c6300SRichard Henderson 3198951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg) 3199951c6300SRichard Henderson { 32003a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 3201951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(ret), arg); 3202951c6300SRichard Henderson tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); 32033a13c3f3SRichard Henderson } else { 3204b7e8b17aSRichard Henderson tcg_gen_op2(INDEX_op_ext_i32_i64, 3205ae8b75dcSRichard Henderson tcgv_i64_arg(ret), tcgv_i32_arg(arg)); 32063a13c3f3SRichard Henderson } 3207951c6300SRichard Henderson } 3208951c6300SRichard Henderson 3209951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) 3210951c6300SRichard Henderson { 32113a13c3f3SRichard Henderson TCGv_i64 tmp; 32123a13c3f3SRichard Henderson 32133a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 3214951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_LOW(dest), low); 3215951c6300SRichard Henderson tcg_gen_mov_i32(TCGV_HIGH(dest), high); 32163a13c3f3SRichard Henderson return; 32173a13c3f3SRichard Henderson } 32183a13c3f3SRichard Henderson 32195dd48602SRichard Henderson tmp = tcg_temp_ebb_new_i64(); 3220951c6300SRichard Henderson /* These extensions are only needed for type correctness. 3221951c6300SRichard Henderson We may be able to do better given target specific information. */ 3222951c6300SRichard Henderson tcg_gen_extu_i32_i64(tmp, high); 3223951c6300SRichard Henderson tcg_gen_extu_i32_i64(dest, low); 3224951c6300SRichard Henderson /* If deposit is available, use it. Otherwise use the extra 3225951c6300SRichard Henderson knowledge that we have of the zero-extensions above. */ 3226951c6300SRichard Henderson if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { 3227951c6300SRichard Henderson tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); 3228951c6300SRichard Henderson } else { 3229951c6300SRichard Henderson tcg_gen_shli_i64(tmp, tmp, 32); 3230951c6300SRichard Henderson tcg_gen_or_i64(dest, dest, tmp); 3231951c6300SRichard Henderson } 3232951c6300SRichard Henderson tcg_temp_free_i64(tmp); 3233951c6300SRichard Henderson } 3234951c6300SRichard Henderson 3235951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg) 3236951c6300SRichard Henderson { 32373a13c3f3SRichard Henderson if (TCG_TARGET_REG_BITS == 32) { 3238951c6300SRichard Henderson tcg_gen_mov_i32(lo, TCGV_LOW(arg)); 3239951c6300SRichard Henderson tcg_gen_mov_i32(hi, TCGV_HIGH(arg)); 32403a13c3f3SRichard Henderson } else { 3241609ad705SRichard Henderson tcg_gen_extrl_i64_i32(lo, arg); 3242609ad705SRichard Henderson tcg_gen_extrh_i64_i32(hi, arg); 32433a13c3f3SRichard Henderson } 3244951c6300SRichard Henderson } 3245951c6300SRichard Henderson 3246951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) 3247951c6300SRichard Henderson { 3248951c6300SRichard Henderson tcg_gen_ext32u_i64(lo, arg); 3249951c6300SRichard Henderson tcg_gen_shri_i64(hi, arg, 32); 3250951c6300SRichard Henderson } 3251951c6300SRichard Henderson 3252e0de2f55SRichard Henderson void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi) 3253e0de2f55SRichard Henderson { 3254e0de2f55SRichard Henderson tcg_gen_deposit_i64(ret, lo, hi, 32, 32); 3255e0de2f55SRichard Henderson } 3256e0de2f55SRichard Henderson 32574771e71cSRichard Henderson void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg) 32584771e71cSRichard Henderson { 32594771e71cSRichard Henderson tcg_gen_mov_i64(lo, TCGV128_LOW(arg)); 32604771e71cSRichard Henderson tcg_gen_mov_i64(hi, TCGV128_HIGH(arg)); 32614771e71cSRichard Henderson } 32624771e71cSRichard Henderson 32634771e71cSRichard Henderson void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi) 32644771e71cSRichard Henderson { 32654771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_LOW(ret), lo); 32664771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_HIGH(ret), hi); 32674771e71cSRichard Henderson } 32684771e71cSRichard Henderson 32694771e71cSRichard Henderson void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src) 32704771e71cSRichard Henderson { 32714771e71cSRichard Henderson if (dst != src) { 32724771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src)); 32734771e71cSRichard Henderson tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src)); 32744771e71cSRichard Henderson } 32754771e71cSRichard Henderson } 32764771e71cSRichard Henderson 3277a01d9792SRichard Henderson void tcg_gen_ld_i128(TCGv_i128 ret, TCGv_ptr base, tcg_target_long offset) 3278a01d9792SRichard Henderson { 3279a01d9792SRichard Henderson if (HOST_BIG_ENDIAN) { 3280a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_HIGH(ret), base, offset); 3281a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_LOW(ret), base, offset + 8); 3282a01d9792SRichard Henderson } else { 3283a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_LOW(ret), base, offset); 3284a01d9792SRichard Henderson tcg_gen_ld_i64(TCGV128_HIGH(ret), base, offset + 8); 3285a01d9792SRichard Henderson } 3286a01d9792SRichard Henderson } 3287a01d9792SRichard Henderson 3288a01d9792SRichard Henderson void tcg_gen_st_i128(TCGv_i128 val, TCGv_ptr base, tcg_target_long offset) 3289a01d9792SRichard Henderson { 3290a01d9792SRichard Henderson if (HOST_BIG_ENDIAN) { 3291a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_HIGH(val), base, offset); 3292a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_LOW(val), base, offset + 8); 3293a01d9792SRichard Henderson } else { 3294a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_LOW(val), base, offset); 3295a01d9792SRichard Henderson tcg_gen_st_i64(TCGV128_HIGH(val), base, offset + 8); 3296a01d9792SRichard Henderson } 3297a01d9792SRichard Henderson } 3298a01d9792SRichard Henderson 3299951c6300SRichard Henderson /* QEMU specific operations. */ 3300951c6300SRichard Henderson 3301d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx) 330207ea28b4SRichard Henderson { 3303eba40358SRichard Henderson /* 3304eba40358SRichard Henderson * Let the jit code return the read-only version of the 3305eba40358SRichard Henderson * TranslationBlock, so that we minimize the pc-relative 3306eba40358SRichard Henderson * distance of the address of the exit_tb code to TB. 3307eba40358SRichard Henderson * This will improve utilization of pc-relative address loads. 3308eba40358SRichard Henderson * 3309eba40358SRichard Henderson * TODO: Move this to translator_loop, so that all const 3310eba40358SRichard Henderson * TranslationBlock pointers refer to read-only memory. 3311eba40358SRichard Henderson * This requires coordination with targets that do not use 3312eba40358SRichard Henderson * the translator_loop. 3313eba40358SRichard Henderson */ 3314eba40358SRichard Henderson uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx; 331507ea28b4SRichard Henderson 331607ea28b4SRichard Henderson if (tb == NULL) { 331707ea28b4SRichard Henderson tcg_debug_assert(idx == 0); 331807ea28b4SRichard Henderson } else if (idx <= TB_EXIT_IDXMAX) { 331907ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG 332007ea28b4SRichard Henderson /* This is an exit following a goto_tb. Verify that we have 332107ea28b4SRichard Henderson seen this numbered exit before, via tcg_gen_goto_tb. */ 332207ea28b4SRichard Henderson tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); 332307ea28b4SRichard Henderson #endif 332407ea28b4SRichard Henderson } else { 332507ea28b4SRichard Henderson /* This is an exit via the exitreq label. */ 332607ea28b4SRichard Henderson tcg_debug_assert(idx == TB_EXIT_REQUESTED); 332707ea28b4SRichard Henderson } 332807ea28b4SRichard Henderson 332907ea28b4SRichard Henderson tcg_gen_op1i(INDEX_op_exit_tb, val); 333007ea28b4SRichard Henderson } 333107ea28b4SRichard Henderson 3332951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx) 3333951c6300SRichard Henderson { 333484f15616SRichard Henderson /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */ 3335b7e4afbdSRichard Henderson tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB)); 3336951c6300SRichard Henderson /* We only support two chained exits. */ 333707ea28b4SRichard Henderson tcg_debug_assert(idx <= TB_EXIT_IDXMAX); 3338951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG 3339a4761232SPhilippe Mathieu-Daudé /* Verify that we haven't seen this numbered exit before. */ 3340b1311c4aSEmilio G. Cota tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0); 3341b1311c4aSEmilio G. Cota tcg_ctx->goto_tb_issue_mask |= 1 << idx; 3342951c6300SRichard Henderson #endif 3343e6d86bedSEmilio G. Cota plugin_gen_disable_mem_helpers(); 3344951c6300SRichard Henderson tcg_gen_op1i(INDEX_op_goto_tb, idx); 3345951c6300SRichard Henderson } 3346951c6300SRichard Henderson 33477f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void) 3348cedbcb01SEmilio G. Cota { 3349e6d86bedSEmilio G. Cota TCGv_ptr ptr; 3350e6d86bedSEmilio G. Cota 3351b7e4afbdSRichard Henderson if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) { 335284f15616SRichard Henderson tcg_gen_exit_tb(NULL, 0); 335384f15616SRichard Henderson return; 335484f15616SRichard Henderson } 335584f15616SRichard Henderson 3356e6d86bedSEmilio G. Cota plugin_gen_disable_mem_helpers(); 33575dd48602SRichard Henderson ptr = tcg_temp_ebb_new_ptr(); 3358ad75a51eSRichard Henderson gen_helper_lookup_tb_ptr(ptr, tcg_env); 3359ae8b75dcSRichard Henderson tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr)); 3360cedbcb01SEmilio G. Cota tcg_temp_free_ptr(ptr); 3361cedbcb01SEmilio G. Cota } 3362