xref: /openbmc/qemu/tcg/tcg-op.c (revision b701f195)
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