xref: /openbmc/qemu/tcg/tcg-op.c (revision b8976aa5)
1951c6300SRichard Henderson /*
2951c6300SRichard Henderson  * Tiny Code Generator for QEMU
3951c6300SRichard Henderson  *
4951c6300SRichard Henderson  * Copyright (c) 2008 Fabrice Bellard
5951c6300SRichard Henderson  *
6951c6300SRichard Henderson  * Permission is hereby granted, free of charge, to any person obtaining a copy
7951c6300SRichard Henderson  * of this software and associated documentation files (the "Software"), to deal
8951c6300SRichard Henderson  * in the Software without restriction, including without limitation the rights
9951c6300SRichard Henderson  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10951c6300SRichard Henderson  * copies of the Software, and to permit persons to whom the Software is
11951c6300SRichard Henderson  * furnished to do so, subject to the following conditions:
12951c6300SRichard Henderson  *
13951c6300SRichard Henderson  * The above copyright notice and this permission notice shall be included in
14951c6300SRichard Henderson  * all copies or substantial portions of the Software.
15951c6300SRichard Henderson  *
16951c6300SRichard Henderson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17951c6300SRichard Henderson  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18951c6300SRichard Henderson  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19951c6300SRichard Henderson  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20951c6300SRichard Henderson  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21951c6300SRichard Henderson  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22951c6300SRichard Henderson  * THE SOFTWARE.
23951c6300SRichard Henderson  */
24951c6300SRichard Henderson 
25757e725bSPeter Maydell #include "qemu/osdep.h"
26dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h"
2747f7313dSRichard Henderson #include "tcg/tcg-temp-internal.h"
28ad3d0e4dSRichard Henderson #include "tcg/tcg-op-common.h"
29cac9b0fdSRichard Henderson #include "exec/translation-block.h"
30e6d86bedSEmilio G. Cota #include "exec/plugin-gen.h"
31d56fea79SRichard Henderson #include "tcg-internal.h"
32951c6300SRichard Henderson 
33951c6300SRichard Henderson 
34b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
35951c6300SRichard Henderson {
36d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 1);
3775e8b9b7SRichard Henderson     op->args[0] = a1;
38951c6300SRichard Henderson }
39951c6300SRichard Henderson 
40b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
41951c6300SRichard Henderson {
42d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 2);
4375e8b9b7SRichard Henderson     op->args[0] = a1;
4475e8b9b7SRichard Henderson     op->args[1] = a2;
45951c6300SRichard Henderson }
46951c6300SRichard Henderson 
47b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
48951c6300SRichard Henderson {
49d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 3);
5075e8b9b7SRichard Henderson     op->args[0] = a1;
5175e8b9b7SRichard Henderson     op->args[1] = a2;
5275e8b9b7SRichard Henderson     op->args[2] = a3;
53951c6300SRichard Henderson }
54951c6300SRichard Henderson 
55b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
56951c6300SRichard Henderson {
57d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 4);
5875e8b9b7SRichard Henderson     op->args[0] = a1;
5975e8b9b7SRichard Henderson     op->args[1] = a2;
6075e8b9b7SRichard Henderson     op->args[2] = a3;
6175e8b9b7SRichard Henderson     op->args[3] = a4;
62951c6300SRichard Henderson }
63951c6300SRichard Henderson 
64b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
65b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5)
66951c6300SRichard Henderson {
67d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 5);
6875e8b9b7SRichard Henderson     op->args[0] = a1;
6975e8b9b7SRichard Henderson     op->args[1] = a2;
7075e8b9b7SRichard Henderson     op->args[2] = a3;
7175e8b9b7SRichard Henderson     op->args[3] = a4;
7275e8b9b7SRichard Henderson     op->args[4] = a5;
73951c6300SRichard Henderson }
74951c6300SRichard Henderson 
75b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
76b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5, TCGArg a6)
77951c6300SRichard Henderson {
78d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 6);
7975e8b9b7SRichard Henderson     op->args[0] = a1;
8075e8b9b7SRichard Henderson     op->args[1] = a2;
8175e8b9b7SRichard Henderson     op->args[2] = a3;
8275e8b9b7SRichard Henderson     op->args[3] = a4;
8375e8b9b7SRichard Henderson     op->args[4] = a5;
8475e8b9b7SRichard Henderson     op->args[5] = a6;
85951c6300SRichard Henderson }
86951c6300SRichard Henderson 
87f85b1fc4SRichard Henderson /* Generic ops.  */
88f85b1fc4SRichard Henderson 
89f85b1fc4SRichard Henderson static void add_last_as_label_use(TCGLabel *l)
90f85b1fc4SRichard Henderson {
91f85b1fc4SRichard Henderson     TCGLabelUse *u = tcg_malloc(sizeof(TCGLabelUse));
92f85b1fc4SRichard Henderson 
93f85b1fc4SRichard Henderson     u->op = tcg_last_op();
94f85b1fc4SRichard Henderson     QSIMPLEQ_INSERT_TAIL(&l->branches, u, next);
95f85b1fc4SRichard Henderson }
96f85b1fc4SRichard Henderson 
97f85b1fc4SRichard Henderson void tcg_gen_br(TCGLabel *l)
98f85b1fc4SRichard Henderson {
99f85b1fc4SRichard Henderson     tcg_gen_op1(INDEX_op_br, label_arg(l));
100f85b1fc4SRichard Henderson     add_last_as_label_use(l);
101f85b1fc4SRichard Henderson }
102f85b1fc4SRichard Henderson 
103f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
104f65e19bcSPranith Kumar {
105c914d46dSRichard Henderson #ifdef CONFIG_USER_ONLY
106c914d46dSRichard Henderson     bool parallel = tcg_ctx->gen_tb->cflags & CF_PARALLEL;
107c914d46dSRichard Henderson #else
108c914d46dSRichard Henderson     /*
109c914d46dSRichard Henderson      * It is tempting to elide the barrier in a uniprocessor context.
110c914d46dSRichard Henderson      * However, even with a single cpu we have i/o threads running in
111c914d46dSRichard Henderson      * parallel, and lack of memory order can result in e.g. virtio
112c914d46dSRichard Henderson      * queue entries being read incorrectly.
113c914d46dSRichard Henderson      */
114c914d46dSRichard Henderson     bool parallel = true;
115c914d46dSRichard Henderson #endif
116c914d46dSRichard Henderson 
117c914d46dSRichard Henderson     if (parallel) {
118b7e8b17aSRichard Henderson         tcg_gen_op1(INDEX_op_mb, mb_type);
119f65e19bcSPranith Kumar     }
120f65e19bcSPranith Kumar }
121f65e19bcSPranith Kumar 
122951c6300SRichard Henderson /* 32 bit ops */
123951c6300SRichard Henderson 
12411d11d61SRichard Henderson void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
12511d11d61SRichard Henderson {
12611d11d61SRichard Henderson     tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
12711d11d61SRichard Henderson }
12811d11d61SRichard Henderson 
129951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
130951c6300SRichard Henderson {
131951c6300SRichard Henderson     /* some cases can be optimized here */
132951c6300SRichard Henderson     if (arg2 == 0) {
133951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
134951c6300SRichard Henderson     } else {
13511d11d61SRichard Henderson         tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
136951c6300SRichard Henderson     }
137951c6300SRichard Henderson }
138951c6300SRichard Henderson 
139951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
140951c6300SRichard Henderson {
141951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
142951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
143951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
144951c6300SRichard Henderson     } else {
14511d11d61SRichard Henderson         tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
146951c6300SRichard Henderson     }
147951c6300SRichard Henderson }
148951c6300SRichard Henderson 
149951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
150951c6300SRichard Henderson {
151951c6300SRichard Henderson     /* some cases can be optimized here */
152951c6300SRichard Henderson     if (arg2 == 0) {
153951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
154951c6300SRichard Henderson     } else {
15511d11d61SRichard Henderson         tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
156951c6300SRichard Henderson     }
157951c6300SRichard Henderson }
158951c6300SRichard Henderson 
159474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
160951c6300SRichard Henderson {
161951c6300SRichard Henderson     /* Some cases can be optimized here.  */
162951c6300SRichard Henderson     switch (arg2) {
163951c6300SRichard Henderson     case 0:
164951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
165951c6300SRichard Henderson         return;
166474b2e8fSRichard Henderson     case -1:
167951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
168951c6300SRichard Henderson         return;
169474b2e8fSRichard Henderson     case 0xff:
170951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
171951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
172951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
173951c6300SRichard Henderson             return;
174951c6300SRichard Henderson         }
175951c6300SRichard Henderson         break;
176474b2e8fSRichard Henderson     case 0xffff:
177951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
178951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
179951c6300SRichard Henderson             return;
180951c6300SRichard Henderson         }
181951c6300SRichard Henderson         break;
182951c6300SRichard Henderson     }
18311d11d61SRichard Henderson 
18411d11d61SRichard Henderson     tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
185951c6300SRichard Henderson }
186951c6300SRichard Henderson 
187951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
188951c6300SRichard Henderson {
189951c6300SRichard Henderson     /* Some cases can be optimized here.  */
190951c6300SRichard Henderson     if (arg2 == -1) {
191951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
192951c6300SRichard Henderson     } else if (arg2 == 0) {
193951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
194951c6300SRichard Henderson     } else {
19511d11d61SRichard Henderson         tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
196951c6300SRichard Henderson     }
197951c6300SRichard Henderson }
198951c6300SRichard Henderson 
199951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
200951c6300SRichard Henderson {
201951c6300SRichard Henderson     /* Some cases can be optimized here.  */
202951c6300SRichard Henderson     if (arg2 == 0) {
203951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
204951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
205951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
206951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
207951c6300SRichard Henderson     } else {
20811d11d61SRichard Henderson         tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
209951c6300SRichard Henderson     }
210951c6300SRichard Henderson }
211951c6300SRichard Henderson 
212474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
213951c6300SRichard Henderson {
214474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
215951c6300SRichard Henderson     if (arg2 == 0) {
216951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
217951c6300SRichard Henderson     } else {
21811d11d61SRichard Henderson         tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2));
219951c6300SRichard Henderson     }
220951c6300SRichard Henderson }
221951c6300SRichard Henderson 
222474b2e8fSRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
223951c6300SRichard Henderson {
224474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
225951c6300SRichard Henderson     if (arg2 == 0) {
226951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
227951c6300SRichard Henderson     } else {
22811d11d61SRichard Henderson         tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2));
229951c6300SRichard Henderson     }
230951c6300SRichard Henderson }
231951c6300SRichard Henderson 
232474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
233951c6300SRichard Henderson {
234474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
235951c6300SRichard Henderson     if (arg2 == 0) {
236951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
237951c6300SRichard Henderson     } else {
23811d11d61SRichard Henderson         tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2));
239951c6300SRichard Henderson     }
240951c6300SRichard Henderson }
241951c6300SRichard Henderson 
24242a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
243951c6300SRichard Henderson {
244951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
24542a268c2SRichard Henderson         tcg_gen_br(l);
246951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
24742a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
248f85b1fc4SRichard Henderson         add_last_as_label_use(l);
249951c6300SRichard Henderson     }
250951c6300SRichard Henderson }
251951c6300SRichard Henderson 
25242a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
253951c6300SRichard Henderson {
25437ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
25537ed3bf1SRichard Henderson         tcg_gen_br(l);
25637ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
25711d11d61SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l);
258951c6300SRichard Henderson     }
25937ed3bf1SRichard Henderson }
260951c6300SRichard Henderson 
261951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
262951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
263951c6300SRichard Henderson {
264951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
265951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
266951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
267951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
268951c6300SRichard Henderson     } else {
269951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
270951c6300SRichard Henderson     }
271951c6300SRichard Henderson }
272951c6300SRichard Henderson 
273951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
274951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
275951c6300SRichard Henderson {
27611d11d61SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2));
277951c6300SRichard Henderson }
278951c6300SRichard Henderson 
2793635502dSRichard Henderson void tcg_gen_negsetcond_i32(TCGCond cond, TCGv_i32 ret,
2803635502dSRichard Henderson                             TCGv_i32 arg1, TCGv_i32 arg2)
2813635502dSRichard Henderson {
2823635502dSRichard Henderson     if (cond == TCG_COND_ALWAYS) {
2833635502dSRichard Henderson         tcg_gen_movi_i32(ret, -1);
2843635502dSRichard Henderson     } else if (cond == TCG_COND_NEVER) {
2853635502dSRichard Henderson         tcg_gen_movi_i32(ret, 0);
2863635502dSRichard Henderson     } else if (TCG_TARGET_HAS_negsetcond_i32) {
2873635502dSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_negsetcond_i32, ret, arg1, arg2, cond);
2883635502dSRichard Henderson     } else {
2893635502dSRichard Henderson         tcg_gen_setcond_i32(cond, ret, arg1, arg2);
2903635502dSRichard Henderson         tcg_gen_neg_i32(ret, ret);
2913635502dSRichard Henderson     }
2923635502dSRichard Henderson }
2933635502dSRichard Henderson 
294951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
295951c6300SRichard Henderson {
296b2e3ae94SRichard Henderson     if (arg2 == 0) {
297b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
298b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
299b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
300b2e3ae94SRichard Henderson     } else {
30111d11d61SRichard Henderson         tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2));
302951c6300SRichard Henderson     }
303b2e3ae94SRichard Henderson }
304951c6300SRichard Henderson 
305951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
306951c6300SRichard Henderson {
307951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
308951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
309951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3105dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
311951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
312951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
313951c6300SRichard Henderson         tcg_temp_free_i32(t0);
314951c6300SRichard Henderson     } else {
315951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
316951c6300SRichard Henderson     }
317951c6300SRichard Henderson }
318951c6300SRichard Henderson 
319951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
320951c6300SRichard Henderson {
321951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
322951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
323951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
3245dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
325951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
326951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
327951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
328951c6300SRichard Henderson         tcg_temp_free_i32(t0);
329951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3305dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
331951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
332951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
333951c6300SRichard Henderson         tcg_temp_free_i32(t0);
334951c6300SRichard Henderson     } else {
335951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
336951c6300SRichard Henderson     }
337951c6300SRichard Henderson }
338951c6300SRichard Henderson 
339951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
340951c6300SRichard Henderson {
341951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
342951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
343951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3445dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
345951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
346951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
347951c6300SRichard Henderson         tcg_temp_free_i32(t0);
348951c6300SRichard Henderson     } else {
349951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
350951c6300SRichard Henderson     }
351951c6300SRichard Henderson }
352951c6300SRichard Henderson 
353951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
354951c6300SRichard Henderson {
355951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
356951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
357951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
3585dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
359951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
360951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
361951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
362951c6300SRichard Henderson         tcg_temp_free_i32(t0);
363951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3645dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
365951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
366951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
367951c6300SRichard Henderson         tcg_temp_free_i32(t0);
368951c6300SRichard Henderson     } else {
369951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
370951c6300SRichard Henderson     }
371951c6300SRichard Henderson }
372951c6300SRichard Henderson 
373951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
374951c6300SRichard Henderson {
375951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
376951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
377951c6300SRichard Henderson     } else {
3785dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
379951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
380951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
381951c6300SRichard Henderson         tcg_temp_free_i32(t0);
382951c6300SRichard Henderson     }
383951c6300SRichard Henderson }
384951c6300SRichard Henderson 
385951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
386951c6300SRichard Henderson {
387951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
388951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
389951c6300SRichard Henderson     } else {
390951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
391951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
392951c6300SRichard Henderson     }
393951c6300SRichard Henderson }
394951c6300SRichard Henderson 
395951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
396951c6300SRichard Henderson {
397951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
398951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
399951c6300SRichard Henderson     } else {
400951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
401951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
402951c6300SRichard Henderson     }
403951c6300SRichard Henderson }
404951c6300SRichard Henderson 
405951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
406951c6300SRichard Henderson {
407951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
408951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
409951c6300SRichard Henderson     } else {
410951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
411951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
412951c6300SRichard Henderson     }
413951c6300SRichard Henderson }
414951c6300SRichard Henderson 
415951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
416951c6300SRichard Henderson {
417951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
418951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
419951c6300SRichard Henderson     } else {
4205dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
421951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
422951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
423951c6300SRichard Henderson         tcg_temp_free_i32(t0);
424951c6300SRichard Henderson     }
425951c6300SRichard Henderson }
426951c6300SRichard Henderson 
4270e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4280e28d006SRichard Henderson {
4290e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4300e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
4310e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
4325dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
4335dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
4340e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4350e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4360e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4370e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4380e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4390e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4400e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4410e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4420e28d006SRichard Henderson     } else {
4430e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4440e28d006SRichard Henderson     }
4450e28d006SRichard Henderson }
4460e28d006SRichard Henderson 
4470e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4480e28d006SRichard Henderson {
44911d11d61SRichard Henderson     tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2));
4500e28d006SRichard Henderson }
4510e28d006SRichard Henderson 
4520e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4530e28d006SRichard Henderson {
4540e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4550e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4560e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4575dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
4585dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
4590e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4600e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4610e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4620e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4630e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4640e28d006SRichard Henderson         tcg_temp_free_i64(t2);
46514e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
46614e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
46714e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
46814e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
4695dd48602SRichard Henderson         TCGv_i32 z, t = tcg_temp_ebb_new_i32();
47014e99210SRichard Henderson 
47114e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
47214e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
47314e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
47414e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
47514e99210SRichard Henderson         } else {
47614e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
47714e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
47814e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
47914e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
48014e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
48114e99210SRichard Henderson         }
48211d11d61SRichard Henderson         z = tcg_constant_i32(0);
48314e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
48414e99210SRichard Henderson         tcg_temp_free_i32(t);
4850e28d006SRichard Henderson     } else {
4860e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4870e28d006SRichard Henderson     }
4880e28d006SRichard Henderson }
4890e28d006SRichard Henderson 
4900e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4910e28d006SRichard Henderson {
49214e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
49314e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
4945dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
49514e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
49614e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
49714e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
49814e99210SRichard Henderson         tcg_temp_free_i32(t);
49914e99210SRichard Henderson     } else {
50011d11d61SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2));
5010e28d006SRichard Henderson     }
50214e99210SRichard Henderson }
5030e28d006SRichard Henderson 
504086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
505086920c2SRichard Henderson {
506086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
5075dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
508086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
509086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
510086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
511086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
512086920c2SRichard Henderson         tcg_temp_free_i32(t);
513086920c2SRichard Henderson     } else {
514086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
515086920c2SRichard Henderson     }
516086920c2SRichard Henderson }
517086920c2SRichard Henderson 
518a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
519a768e4e9SRichard Henderson {
520a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
521a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
522a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
5235dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
524a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
525a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
526a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
527a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
528a768e4e9SRichard Henderson     } else {
529a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
530a768e4e9SRichard Henderson     }
531a768e4e9SRichard Henderson }
532a768e4e9SRichard Henderson 
533951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
534951c6300SRichard Henderson {
535951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
536951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
537951c6300SRichard Henderson     } else {
538951c6300SRichard Henderson         TCGv_i32 t0, t1;
539951c6300SRichard Henderson 
5405dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
5415dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
542951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
543951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
544951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
545951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
546951c6300SRichard Henderson         tcg_temp_free_i32(t0);
547951c6300SRichard Henderson         tcg_temp_free_i32(t1);
548951c6300SRichard Henderson     }
549951c6300SRichard Henderson }
550951c6300SRichard Henderson 
55107dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
552951c6300SRichard Henderson {
55307dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
554951c6300SRichard Henderson     /* some cases can be optimized here */
555951c6300SRichard Henderson     if (arg2 == 0) {
556951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
557951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
55811d11d61SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2));
559951c6300SRichard Henderson     } else {
560951c6300SRichard Henderson         TCGv_i32 t0, t1;
5615dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
5625dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
563951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
564951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
565951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
566951c6300SRichard Henderson         tcg_temp_free_i32(t0);
567951c6300SRichard Henderson         tcg_temp_free_i32(t1);
568951c6300SRichard Henderson     }
569951c6300SRichard Henderson }
570951c6300SRichard Henderson 
571951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
572951c6300SRichard Henderson {
573951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
574951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
575951c6300SRichard Henderson     } else {
576951c6300SRichard Henderson         TCGv_i32 t0, t1;
577951c6300SRichard Henderson 
5785dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
5795dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
580951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
581951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
582951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
583951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
584951c6300SRichard Henderson         tcg_temp_free_i32(t0);
585951c6300SRichard Henderson         tcg_temp_free_i32(t1);
586951c6300SRichard Henderson     }
587951c6300SRichard Henderson }
588951c6300SRichard Henderson 
58907dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
590951c6300SRichard Henderson {
59107dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
592951c6300SRichard Henderson     /* some cases can be optimized here */
593951c6300SRichard Henderson     if (arg2 == 0) {
594951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
595951c6300SRichard Henderson     } else {
596951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
597951c6300SRichard Henderson     }
598951c6300SRichard Henderson }
599951c6300SRichard Henderson 
600951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
601951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
602951c6300SRichard Henderson {
603951c6300SRichard Henderson     uint32_t mask;
604951c6300SRichard Henderson     TCGv_i32 t1;
605951c6300SRichard Henderson 
606951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
6070d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
608951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
609951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
610951c6300SRichard Henderson 
6110d0d309dSRichard Henderson     if (len == 32) {
612951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
613951c6300SRichard Henderson         return;
614951c6300SRichard Henderson     }
615951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
616951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
617951c6300SRichard Henderson         return;
618951c6300SRichard Henderson     }
619951c6300SRichard Henderson 
6205dd48602SRichard Henderson     t1 = tcg_temp_ebb_new_i32();
621951c6300SRichard Henderson 
622b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i32) {
623b0a60567SRichard Henderson         if (ofs + len == 32) {
624b0a60567SRichard Henderson             tcg_gen_shli_i32(t1, arg1, len);
625b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, t1, arg2, len);
626b0a60567SRichard Henderson             goto done;
627b0a60567SRichard Henderson         }
628b0a60567SRichard Henderson         if (ofs == 0) {
629b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, arg1, arg2, len);
630b0a60567SRichard Henderson             tcg_gen_rotli_i32(ret, ret, len);
631b0a60567SRichard Henderson             goto done;
632b0a60567SRichard Henderson         }
633b0a60567SRichard Henderson     }
634b0a60567SRichard Henderson 
635b0a60567SRichard Henderson     mask = (1u << len) - 1;
636951c6300SRichard Henderson     if (ofs + len < 32) {
637951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
638951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
639951c6300SRichard Henderson     } else {
640951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
641951c6300SRichard Henderson     }
642951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
643951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
644b0a60567SRichard Henderson  done:
645951c6300SRichard Henderson     tcg_temp_free_i32(t1);
646951c6300SRichard Henderson }
647951c6300SRichard Henderson 
64807cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
64907cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
65007cc68d5SRichard Henderson {
65107cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
65207cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
65307cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
65407cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
65507cc68d5SRichard Henderson 
65607cc68d5SRichard Henderson     if (ofs + len == 32) {
65707cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
65807cc68d5SRichard Henderson     } else if (ofs == 0) {
65907cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
66007cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
66107cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
66211d11d61SRichard Henderson         TCGv_i32 zero = tcg_constant_i32(0);
66307cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
66407cc68d5SRichard Henderson     } else {
66507cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
66607cc68d5SRichard Henderson            which allows ARG to stay live.  */
66707cc68d5SRichard Henderson         switch (len) {
66807cc68d5SRichard Henderson         case 16:
66907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
67007cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
67107cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
67207cc68d5SRichard Henderson                 return;
67307cc68d5SRichard Henderson             }
67407cc68d5SRichard Henderson             break;
67507cc68d5SRichard Henderson         case 8:
67607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
67707cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
67807cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
67907cc68d5SRichard Henderson                 return;
68007cc68d5SRichard Henderson             }
68107cc68d5SRichard Henderson             break;
68207cc68d5SRichard Henderson         }
68307cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
68407cc68d5SRichard Henderson         switch (ofs + len) {
68507cc68d5SRichard Henderson         case 16:
68607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
68707cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
68807cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
68907cc68d5SRichard Henderson                 return;
69007cc68d5SRichard Henderson             }
69107cc68d5SRichard Henderson             break;
69207cc68d5SRichard Henderson         case 8:
69307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
69407cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
69507cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
69607cc68d5SRichard Henderson                 return;
69707cc68d5SRichard Henderson             }
69807cc68d5SRichard Henderson             break;
69907cc68d5SRichard Henderson         }
70007cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
70107cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
70207cc68d5SRichard Henderson     }
70307cc68d5SRichard Henderson }
70407cc68d5SRichard Henderson 
7057ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
7067ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
7077ec8bab3SRichard Henderson {
7087ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7097ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7107ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7117ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7127ec8bab3SRichard Henderson 
7137ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7147ec8bab3SRichard Henderson     if (ofs + len == 32) {
7157ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
7167ec8bab3SRichard Henderson         return;
7177ec8bab3SRichard Henderson     }
7187ec8bab3SRichard Henderson     if (ofs == 0) {
7197ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
7207ec8bab3SRichard Henderson         return;
7217ec8bab3SRichard Henderson     }
7227ec8bab3SRichard Henderson 
7237ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
7247ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7257ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
7267ec8bab3SRichard Henderson         return;
7277ec8bab3SRichard Henderson     }
7287ec8bab3SRichard Henderson 
7297ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
7307ec8bab3SRichard Henderson     switch (ofs + len) {
7317ec8bab3SRichard Henderson     case 16:
7327ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7337ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7347ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7357ec8bab3SRichard Henderson             return;
7367ec8bab3SRichard Henderson         }
7377ec8bab3SRichard Henderson         break;
7387ec8bab3SRichard Henderson     case 8:
7397ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7407ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7417ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7427ec8bab3SRichard Henderson             return;
7437ec8bab3SRichard Henderson         }
7447ec8bab3SRichard Henderson         break;
7457ec8bab3SRichard Henderson     }
7467ec8bab3SRichard Henderson 
7477ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7487ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7497ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7507ec8bab3SRichard Henderson     switch (len) {
7517ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7527ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7537ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7547ec8bab3SRichard Henderson         break;
7557ec8bab3SRichard Henderson     default:
7567ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7577ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7587ec8bab3SRichard Henderson         break;
7597ec8bab3SRichard Henderson     }
7607ec8bab3SRichard Henderson }
7617ec8bab3SRichard Henderson 
7627ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7637ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7647ec8bab3SRichard Henderson {
7657ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7667ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7677ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7687ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7697ec8bab3SRichard Henderson 
7707ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7717ec8bab3SRichard Henderson     if (ofs + len == 32) {
7727ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7737ec8bab3SRichard Henderson         return;
7747ec8bab3SRichard Henderson     }
7757ec8bab3SRichard Henderson     if (ofs == 0) {
7767ec8bab3SRichard Henderson         switch (len) {
7777ec8bab3SRichard Henderson         case 16:
7787ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7797ec8bab3SRichard Henderson             return;
7807ec8bab3SRichard Henderson         case 8:
7817ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7827ec8bab3SRichard Henderson             return;
7837ec8bab3SRichard Henderson         }
7847ec8bab3SRichard Henderson     }
7857ec8bab3SRichard Henderson 
7867ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7877ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7887ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7897ec8bab3SRichard Henderson         return;
7907ec8bab3SRichard Henderson     }
7917ec8bab3SRichard Henderson 
7927ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7937ec8bab3SRichard Henderson     switch (ofs + len) {
7947ec8bab3SRichard Henderson     case 16:
7957ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7967ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7977ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7987ec8bab3SRichard Henderson             return;
7997ec8bab3SRichard Henderson         }
8007ec8bab3SRichard Henderson         break;
8017ec8bab3SRichard Henderson     case 8:
8027ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8037ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
8047ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
8057ec8bab3SRichard Henderson             return;
8067ec8bab3SRichard Henderson         }
8077ec8bab3SRichard Henderson         break;
8087ec8bab3SRichard Henderson     }
8097ec8bab3SRichard Henderson     switch (len) {
8107ec8bab3SRichard Henderson     case 16:
8117ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
8127ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8137ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
8147ec8bab3SRichard Henderson             return;
8157ec8bab3SRichard Henderson         }
8167ec8bab3SRichard Henderson         break;
8177ec8bab3SRichard Henderson     case 8:
8187ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8197ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8207ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
8217ec8bab3SRichard Henderson             return;
8227ec8bab3SRichard Henderson         }
8237ec8bab3SRichard Henderson         break;
8247ec8bab3SRichard Henderson     }
8257ec8bab3SRichard Henderson 
8267ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
8277ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
8287ec8bab3SRichard Henderson }
8297ec8bab3SRichard Henderson 
8302089fcc9SDavid Hildenbrand /*
8312089fcc9SDavid Hildenbrand  * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
8322089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
8332089fcc9SDavid Hildenbrand  */
8342089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
8352089fcc9SDavid Hildenbrand                           unsigned int ofs)
8362089fcc9SDavid Hildenbrand {
8372089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 32);
8382089fcc9SDavid Hildenbrand     if (ofs == 0) {
8392089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, al);
8402089fcc9SDavid Hildenbrand     } else if (ofs == 32) {
8412089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, ah);
8422089fcc9SDavid Hildenbrand     } else if (al == ah) {
8432089fcc9SDavid Hildenbrand         tcg_gen_rotri_i32(ret, al, ofs);
844fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i32) {
845fce1296fSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
8462089fcc9SDavid Hildenbrand     } else {
8475dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
8482089fcc9SDavid Hildenbrand         tcg_gen_shri_i32(t0, al, ofs);
8492089fcc9SDavid Hildenbrand         tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs);
8502089fcc9SDavid Hildenbrand         tcg_temp_free_i32(t0);
8512089fcc9SDavid Hildenbrand     }
8522089fcc9SDavid Hildenbrand }
8532089fcc9SDavid Hildenbrand 
854951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
855951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
856951c6300SRichard Henderson {
85737ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
85837ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
85937ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
86037ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
86137ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
862951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
863951c6300SRichard Henderson     } else {
8645dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
8655dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
8664a883870SRichard Henderson         tcg_gen_negsetcond_i32(cond, t0, c1, c2);
867951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
868951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
869951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
870951c6300SRichard Henderson         tcg_temp_free_i32(t0);
871951c6300SRichard Henderson         tcg_temp_free_i32(t1);
872951c6300SRichard Henderson     }
873951c6300SRichard Henderson }
874951c6300SRichard Henderson 
875951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
876951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
877951c6300SRichard Henderson {
878951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
879951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
880951c6300SRichard Henderson     } else {
8815dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
8825dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
883951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
884951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
885951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
886951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
887951c6300SRichard Henderson         tcg_temp_free_i64(t0);
888951c6300SRichard Henderson         tcg_temp_free_i64(t1);
889951c6300SRichard Henderson     }
890951c6300SRichard Henderson }
891951c6300SRichard Henderson 
892951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
893951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
894951c6300SRichard Henderson {
895951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
896951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
897951c6300SRichard Henderson     } else {
8985dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
8995dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
900951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
901951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
902951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
903951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
904951c6300SRichard Henderson         tcg_temp_free_i64(t0);
905951c6300SRichard Henderson         tcg_temp_free_i64(t1);
906951c6300SRichard Henderson     }
907951c6300SRichard Henderson }
908951c6300SRichard Henderson 
909951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
910951c6300SRichard Henderson {
911951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
912951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
913951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
9145dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
915951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
916951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
917951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
918951c6300SRichard Henderson         tcg_temp_free_i32(t);
9199fd86b51SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
9205dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
9215dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
922951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
923951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
924951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
925951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
926951c6300SRichard Henderson         tcg_temp_free_i64(t0);
927951c6300SRichard Henderson         tcg_temp_free_i64(t1);
9289fd86b51SRichard Henderson     } else {
9299fd86b51SRichard Henderson         qemu_build_not_reached();
930951c6300SRichard Henderson     }
931951c6300SRichard Henderson }
932951c6300SRichard Henderson 
933951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
934951c6300SRichard Henderson {
935951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
936951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
937951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
9385dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
939951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
940951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
941951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
942951c6300SRichard Henderson         tcg_temp_free_i32(t);
943951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
9445dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
9455dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
9465dd48602SRichard Henderson         TCGv_i32 t2 = tcg_temp_ebb_new_i32();
9475dd48602SRichard Henderson         TCGv_i32 t3 = tcg_temp_ebb_new_i32();
948951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
949951c6300SRichard Henderson         /* Adjust for negative inputs.  */
950951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
951951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
952951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
953951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
954951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
955951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
956951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
957951c6300SRichard Henderson         tcg_temp_free_i32(t0);
958951c6300SRichard Henderson         tcg_temp_free_i32(t1);
959951c6300SRichard Henderson         tcg_temp_free_i32(t2);
960951c6300SRichard Henderson         tcg_temp_free_i32(t3);
961951c6300SRichard Henderson     } else {
9625dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
9635dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
964951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
965951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
966951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
967951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
968951c6300SRichard Henderson         tcg_temp_free_i64(t0);
969951c6300SRichard Henderson         tcg_temp_free_i64(t1);
970951c6300SRichard Henderson     }
971951c6300SRichard Henderson }
972951c6300SRichard Henderson 
9735087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9745087abfbSRichard Henderson {
9755087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9765dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
9775dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
9785dd48602SRichard Henderson         TCGv_i32 t2 = tcg_temp_ebb_new_i32();
9795087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9805087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9815087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9825087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9835087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9845087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9855087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9865087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9875087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9885087abfbSRichard Henderson     } else {
9895dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
9905dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
9915087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9925087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9935087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9945087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9955087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9965087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9975087abfbSRichard Henderson     }
9985087abfbSRichard Henderson }
9995087abfbSRichard Henderson 
1000951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
1001951c6300SRichard Henderson {
1002951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
1003951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
1004951c6300SRichard Henderson     } else {
1005951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
1006951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
1007951c6300SRichard Henderson     }
1008951c6300SRichard Henderson }
1009951c6300SRichard Henderson 
1010951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
1011951c6300SRichard Henderson {
1012951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
1013951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
1014951c6300SRichard Henderson     } else {
1015951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
1016951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
1017951c6300SRichard Henderson     }
1018951c6300SRichard Henderson }
1019951c6300SRichard Henderson 
1020951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
1021951c6300SRichard Henderson {
1022951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
1023951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
1024951c6300SRichard Henderson     } else {
1025951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
1026951c6300SRichard Henderson     }
1027951c6300SRichard Henderson }
1028951c6300SRichard Henderson 
1029951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
1030951c6300SRichard Henderson {
1031951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
1032951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
1033951c6300SRichard Henderson     } else {
1034951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1035951c6300SRichard Henderson     }
1036951c6300SRichard Henderson }
1037951c6300SRichard Henderson 
10384de5a76aSPhilippe Mathieu-Daudé /*
10394de5a76aSPhilippe Mathieu-Daudé  * bswap16_i32: 16-bit byte swap on the low bits of a 32-bit value.
10404de5a76aSPhilippe Mathieu-Daudé  *
10414de5a76aSPhilippe Mathieu-Daudé  * Byte pattern: xxab -> yyba
10424de5a76aSPhilippe Mathieu-Daudé  *
10434de5a76aSPhilippe Mathieu-Daudé  * With TCG_BSWAP_IZ, x == zero, else undefined.
10444de5a76aSPhilippe Mathieu-Daudé  * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined.
10454de5a76aSPhilippe Mathieu-Daudé  */
10462b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
1047951c6300SRichard Henderson {
10482b836c2aSRichard Henderson     /* Only one extension flag may be present. */
10492b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
10502b836c2aSRichard Henderson 
1051951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
10522b836c2aSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags);
1053951c6300SRichard Henderson     } else {
10545dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
10555dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
1056951c6300SRichard Henderson 
10574de5a76aSPhilippe Mathieu-Daudé                                             /* arg = ..ab (IZ) xxab (!IZ) */
10584de5a76aSPhilippe Mathieu-Daudé         tcg_gen_shri_i32(t0, arg, 8);       /*  t0 = ...a (IZ) .xxa (!IZ) */
10592b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
10604de5a76aSPhilippe Mathieu-Daudé             tcg_gen_ext8u_i32(t0, t0);      /*  t0 = ...a */
10612b836c2aSRichard Henderson         }
10622b836c2aSRichard Henderson 
10632b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
10644de5a76aSPhilippe Mathieu-Daudé             tcg_gen_shli_i32(t1, arg, 24);  /*  t1 = b... */
10654de5a76aSPhilippe Mathieu-Daudé             tcg_gen_sari_i32(t1, t1, 16);   /*  t1 = ssb. */
10662b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
10674de5a76aSPhilippe Mathieu-Daudé             tcg_gen_ext8u_i32(t1, arg);     /*  t1 = ...b */
10684de5a76aSPhilippe Mathieu-Daudé             tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = ..b. */
10692b836c2aSRichard Henderson         } else {
10704de5a76aSPhilippe Mathieu-Daudé             tcg_gen_shli_i32(t1, arg, 8);   /*  t1 = xab. */
10712b836c2aSRichard Henderson         }
10722b836c2aSRichard Henderson 
10734de5a76aSPhilippe Mathieu-Daudé         tcg_gen_or_i32(ret, t0, t1);        /* ret = ..ba (OZ) */
10744de5a76aSPhilippe Mathieu-Daudé                                             /*     = ssba (OS) */
10754de5a76aSPhilippe Mathieu-Daudé                                             /*     = xaba (no flag) */
1076951c6300SRichard Henderson         tcg_temp_free_i32(t0);
10772b836c2aSRichard Henderson         tcg_temp_free_i32(t1);
1078951c6300SRichard Henderson     }
1079951c6300SRichard Henderson }
1080951c6300SRichard Henderson 
108192964556SPhilippe Mathieu-Daudé /*
108292964556SPhilippe Mathieu-Daudé  * bswap32_i32: 32-bit byte swap on a 32-bit value.
108392964556SPhilippe Mathieu-Daudé  *
108492964556SPhilippe Mathieu-Daudé  * Byte pattern: abcd -> dcba
108592964556SPhilippe Mathieu-Daudé  */
1086951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1087951c6300SRichard Henderson {
1088951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1089587195bdSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
1090951c6300SRichard Henderson     } else {
10915dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
10925dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
109311d11d61SRichard Henderson         TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
1094951c6300SRichard Henderson 
1095a686dc71SRichard Henderson                                         /* arg = abcd */
1096a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);   /*  t0 = .abc */
1097a686dc71SRichard Henderson         tcg_gen_and_i32(t1, arg, t2);   /*  t1 = .b.d */
1098a686dc71SRichard Henderson         tcg_gen_and_i32(t0, t0, t2);    /*  t0 = .a.c */
1099a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = b.d. */
1100a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = badc */
1101951c6300SRichard Henderson 
1102a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, ret, 16);  /*  t0 = ..ba */
1103a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, ret, 16);  /*  t1 = dc.. */
1104a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = dcba */
1105951c6300SRichard Henderson 
1106951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1107951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1108951c6300SRichard Henderson     }
1109951c6300SRichard Henderson }
1110951c6300SRichard Henderson 
1111*b8976aa5SPhilippe Mathieu-Daudé /*
1112*b8976aa5SPhilippe Mathieu-Daudé  * hswap_i32: Swap 16-bit halfwords within a 32-bit value.
1113*b8976aa5SPhilippe Mathieu-Daudé  *
1114*b8976aa5SPhilippe Mathieu-Daudé  * Byte pattern: abcd -> cdab
1115*b8976aa5SPhilippe Mathieu-Daudé  */
111646be8425SRichard Henderson void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg)
111746be8425SRichard Henderson {
111846be8425SRichard Henderson     /* Swapping 2 16-bit elements is a rotate. */
111946be8425SRichard Henderson     tcg_gen_rotli_i32(ret, arg, 16);
112046be8425SRichard Henderson }
112146be8425SRichard Henderson 
1122b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1123b87fb8cdSRichard Henderson {
1124b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1125b87fb8cdSRichard Henderson }
1126b87fb8cdSRichard Henderson 
1127b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1128b87fb8cdSRichard Henderson {
1129b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1130b87fb8cdSRichard Henderson }
1131b87fb8cdSRichard Henderson 
1132b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1133b87fb8cdSRichard Henderson {
1134b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1135b87fb8cdSRichard Henderson }
1136b87fb8cdSRichard Henderson 
1137b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1138b87fb8cdSRichard Henderson {
1139b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1140b87fb8cdSRichard Henderson }
1141b87fb8cdSRichard Henderson 
1142ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
1143ff1f11f7SRichard Henderson {
11445dd48602SRichard Henderson     TCGv_i32 t = tcg_temp_ebb_new_i32();
1145ff1f11f7SRichard Henderson 
1146ff1f11f7SRichard Henderson     tcg_gen_sari_i32(t, a, 31);
1147ff1f11f7SRichard Henderson     tcg_gen_xor_i32(ret, a, t);
1148ff1f11f7SRichard Henderson     tcg_gen_sub_i32(ret, ret, t);
1149ff1f11f7SRichard Henderson     tcg_temp_free_i32(t);
1150ff1f11f7SRichard Henderson }
1151ff1f11f7SRichard Henderson 
1152951c6300SRichard Henderson /* 64-bit ops */
1153951c6300SRichard Henderson 
1154951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1155951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1156951c6300SRichard Henderson 
1157951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1158951c6300SRichard Henderson {
1159951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1160951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1161951c6300SRichard Henderson }
1162951c6300SRichard Henderson 
1163951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1164951c6300SRichard Henderson {
116511d11d61SRichard Henderson     TCGTemp *ts = tcgv_i64_temp(arg);
116611d11d61SRichard Henderson 
116711d11d61SRichard Henderson     /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
116811d11d61SRichard Henderson     if (ts->kind == TEMP_CONST) {
116911d11d61SRichard Henderson         tcg_gen_movi_i64(ret, ts->val);
117011d11d61SRichard Henderson     } else {
1171951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1172951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1173951c6300SRichard Henderson     }
117411d11d61SRichard Henderson }
1175951c6300SRichard Henderson 
1176951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1177951c6300SRichard Henderson {
1178951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1179951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1180951c6300SRichard Henderson }
1181951c6300SRichard Henderson 
1182951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1183951c6300SRichard Henderson {
1184951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1185951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1186951c6300SRichard Henderson }
1187951c6300SRichard Henderson 
1188951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1189951c6300SRichard Henderson {
1190951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11913ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1192951c6300SRichard Henderson }
1193951c6300SRichard Henderson 
1194951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1195951c6300SRichard Henderson {
1196951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1197951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1198951c6300SRichard Henderson }
1199951c6300SRichard Henderson 
1200951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1201951c6300SRichard Henderson {
1202951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1203951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1204951c6300SRichard Henderson }
1205951c6300SRichard Henderson 
1206951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1207951c6300SRichard Henderson {
1208951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1209951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1210951c6300SRichard Henderson }
1211951c6300SRichard Henderson 
1212951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1213951c6300SRichard Henderson {
1214951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1215951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1216951c6300SRichard Henderson }
1217951c6300SRichard Henderson 
1218951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1219951c6300SRichard Henderson {
1220951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1221951c6300SRichard Henderson        they cannot be the same temporary */
1222e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1223951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1224951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1225951c6300SRichard Henderson #else
1226951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1227951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1228951c6300SRichard Henderson #endif
1229951c6300SRichard Henderson }
1230951c6300SRichard Henderson 
1231d56fea79SRichard Henderson void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1232d56fea79SRichard Henderson {
1233d56fea79SRichard Henderson     tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset);
1234d56fea79SRichard Henderson }
1235d56fea79SRichard Henderson 
1236d56fea79SRichard Henderson void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1237d56fea79SRichard Henderson {
1238d56fea79SRichard Henderson     tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset);
1239d56fea79SRichard Henderson }
1240d56fea79SRichard Henderson 
1241d56fea79SRichard Henderson void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1242d56fea79SRichard Henderson {
1243d56fea79SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1244d56fea79SRichard Henderson }
1245d56fea79SRichard Henderson 
1246951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1247951c6300SRichard Henderson {
1248e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1249951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1250951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1251951c6300SRichard Henderson #else
1252951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1253951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1254951c6300SRichard Henderson #endif
1255951c6300SRichard Henderson }
1256951c6300SRichard Henderson 
1257d56fea79SRichard Henderson void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1258d56fea79SRichard Henderson {
1259d56fea79SRichard Henderson     tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1),
1260d56fea79SRichard Henderson                      TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2));
1261d56fea79SRichard Henderson }
1262d56fea79SRichard Henderson 
1263d56fea79SRichard Henderson void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1264d56fea79SRichard Henderson {
1265d56fea79SRichard Henderson     tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1),
1266d56fea79SRichard Henderson                      TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2));
1267d56fea79SRichard Henderson }
1268d56fea79SRichard Henderson 
1269951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1270951c6300SRichard Henderson {
1271951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1272951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1273951c6300SRichard Henderson }
1274951c6300SRichard Henderson 
1275951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1276951c6300SRichard Henderson {
1277951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1278951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1279951c6300SRichard Henderson }
1280951c6300SRichard Henderson 
1281951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1282951c6300SRichard Henderson {
1283951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1284951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1285951c6300SRichard Henderson }
1286951c6300SRichard Henderson 
1287951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1288951c6300SRichard Henderson {
1289951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1290951c6300SRichard Henderson }
1291951c6300SRichard Henderson 
1292951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1293951c6300SRichard Henderson {
1294951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1295951c6300SRichard Henderson }
1296951c6300SRichard Henderson 
1297951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1298951c6300SRichard Henderson {
1299951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1300951c6300SRichard Henderson }
1301951c6300SRichard Henderson 
1302951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1303951c6300SRichard Henderson {
1304951c6300SRichard Henderson     TCGv_i64 t0;
1305951c6300SRichard Henderson     TCGv_i32 t1;
1306951c6300SRichard Henderson 
13075dd48602SRichard Henderson     t0 = tcg_temp_ebb_new_i64();
13085dd48602SRichard Henderson     t1 = tcg_temp_ebb_new_i32();
1309951c6300SRichard Henderson 
1310951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1311951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1312951c6300SRichard Henderson 
1313951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1314951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1315951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1316951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1317951c6300SRichard Henderson 
1318951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1319951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1320951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1321951c6300SRichard Henderson }
132211d11d61SRichard Henderson 
132311d11d61SRichard Henderson #else
132411d11d61SRichard Henderson 
132511d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
132611d11d61SRichard Henderson {
132711d11d61SRichard Henderson     tcg_gen_mov_i64(ret, tcg_constant_i64(arg));
132811d11d61SRichard Henderson }
132911d11d61SRichard Henderson 
1330951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1331951c6300SRichard Henderson 
1332951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1333951c6300SRichard Henderson {
1334951c6300SRichard Henderson     /* some cases can be optimized here */
1335951c6300SRichard Henderson     if (arg2 == 0) {
1336951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
133711d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
133811d11d61SRichard Henderson         tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2));
1339951c6300SRichard Henderson     } else {
134011d11d61SRichard Henderson         tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
134111d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
134211d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1343951c6300SRichard Henderson     }
1344951c6300SRichard Henderson }
1345951c6300SRichard Henderson 
1346951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1347951c6300SRichard Henderson {
1348951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1349951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1350951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
135111d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
135211d11d61SRichard Henderson         tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
1353951c6300SRichard Henderson     } else {
135411d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
135511d11d61SRichard Henderson                          tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32),
135611d11d61SRichard Henderson                          TCGV_LOW(arg2), TCGV_HIGH(arg2));
1357951c6300SRichard Henderson     }
1358951c6300SRichard Henderson }
1359951c6300SRichard Henderson 
1360951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1361951c6300SRichard Henderson {
1362951c6300SRichard Henderson     /* some cases can be optimized here */
1363951c6300SRichard Henderson     if (arg2 == 0) {
1364951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
136511d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
136611d11d61SRichard Henderson         tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2));
1367951c6300SRichard Henderson     } else {
136811d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
136911d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
137011d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1371951c6300SRichard Henderson     }
1372951c6300SRichard Henderson }
1373951c6300SRichard Henderson 
1374474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1375951c6300SRichard Henderson {
13763a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1377951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1378951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13793a13c3f3SRichard Henderson         return;
13803a13c3f3SRichard Henderson     }
13813a13c3f3SRichard Henderson 
1382951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1383951c6300SRichard Henderson     switch (arg2) {
1384951c6300SRichard Henderson     case 0:
1385951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1386951c6300SRichard Henderson         return;
1387474b2e8fSRichard Henderson     case -1:
1388951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1389951c6300SRichard Henderson         return;
1390474b2e8fSRichard Henderson     case 0xff:
1391951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1392951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1393951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1394951c6300SRichard Henderson             return;
1395951c6300SRichard Henderson         }
1396951c6300SRichard Henderson         break;
1397474b2e8fSRichard Henderson     case 0xffff:
1398951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1399951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1400951c6300SRichard Henderson             return;
1401951c6300SRichard Henderson         }
1402951c6300SRichard Henderson         break;
1403474b2e8fSRichard Henderson     case 0xffffffffu:
1404951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1405951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1406951c6300SRichard Henderson             return;
1407951c6300SRichard Henderson         }
1408951c6300SRichard Henderson         break;
1409951c6300SRichard Henderson     }
141011d11d61SRichard Henderson 
141111d11d61SRichard Henderson     tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2));
1412951c6300SRichard Henderson }
1413951c6300SRichard Henderson 
1414951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1415951c6300SRichard Henderson {
14163a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1417951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1418951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
14193a13c3f3SRichard Henderson         return;
14203a13c3f3SRichard Henderson     }
1421951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1422951c6300SRichard Henderson     if (arg2 == -1) {
1423951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1424951c6300SRichard Henderson     } else if (arg2 == 0) {
1425951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1426951c6300SRichard Henderson     } else {
142711d11d61SRichard Henderson         tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2));
1428951c6300SRichard Henderson     }
1429951c6300SRichard Henderson }
1430951c6300SRichard Henderson 
1431951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1432951c6300SRichard Henderson {
14333a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1434951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1435951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
14363a13c3f3SRichard Henderson         return;
14373a13c3f3SRichard Henderson     }
1438951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1439951c6300SRichard Henderson     if (arg2 == 0) {
1440951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1441951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1442951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1443951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1444951c6300SRichard Henderson     } else {
144511d11d61SRichard Henderson         tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2));
1446951c6300SRichard Henderson     }
1447951c6300SRichard Henderson }
1448951c6300SRichard Henderson 
1449951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1450951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1451951c6300SRichard Henderson {
1452951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1453951c6300SRichard Henderson     if (c == 0) {
1454951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1455951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1456951c6300SRichard Henderson     } else if (c >= 32) {
1457951c6300SRichard Henderson         c -= 32;
1458951c6300SRichard Henderson         if (right) {
1459951c6300SRichard Henderson             if (arith) {
1460951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1461951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1462951c6300SRichard Henderson             } else {
1463951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1464951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1465951c6300SRichard Henderson             }
1466951c6300SRichard Henderson         } else {
1467951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1468951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1469951c6300SRichard Henderson         }
147002616badSRichard Henderson     } else if (right) {
147102616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
147202616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_LOW(ret),
147302616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1474951c6300SRichard Henderson         } else {
1475951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
147602616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret),
147702616badSRichard Henderson                                 TCGV_HIGH(arg1), 32 - c, c);
1478951c6300SRichard Henderson         }
147902616badSRichard Henderson         if (arith) {
148002616badSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
148102616badSRichard Henderson         } else {
148202616badSRichard Henderson             tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
148302616badSRichard Henderson         }
148402616badSRichard Henderson     } else {
148502616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
148602616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_HIGH(ret),
148702616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
148802616badSRichard Henderson         } else {
14895dd48602SRichard Henderson             TCGv_i32 t0 = tcg_temp_ebb_new_i32();
149002616badSRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
149102616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), t0,
149202616badSRichard Henderson                                 TCGV_HIGH(arg1), c, 32 - c);
1493951c6300SRichard Henderson             tcg_temp_free_i32(t0);
149402616badSRichard Henderson         }
149502616badSRichard Henderson         tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1496951c6300SRichard Henderson     }
1497951c6300SRichard Henderson }
1498951c6300SRichard Henderson 
1499474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1500951c6300SRichard Henderson {
1501474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
15023a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
15033a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
15043a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1505951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1506951c6300SRichard Henderson     } else {
150711d11d61SRichard Henderson         tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2));
1508951c6300SRichard Henderson     }
1509951c6300SRichard Henderson }
1510951c6300SRichard Henderson 
1511474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1512951c6300SRichard Henderson {
1513474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
15143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
15153a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
15163a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1517951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1518951c6300SRichard Henderson     } else {
151911d11d61SRichard Henderson         tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2));
1520951c6300SRichard Henderson     }
1521951c6300SRichard Henderson }
1522951c6300SRichard Henderson 
1523474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1524951c6300SRichard Henderson {
1525474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
15263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
15273a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
15283a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1529951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1530951c6300SRichard Henderson     } else {
153111d11d61SRichard Henderson         tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2));
1532951c6300SRichard Henderson     }
1533951c6300SRichard Henderson }
1534951c6300SRichard Henderson 
153542a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1536951c6300SRichard Henderson {
1537951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
153842a268c2SRichard Henderson         tcg_gen_br(l);
1539951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
15403a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1541951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1542951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
154342a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
15443a13c3f3SRichard Henderson         } else {
154542a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
154642a268c2SRichard Henderson                               label_arg(l));
15473a13c3f3SRichard Henderson         }
1548f85b1fc4SRichard Henderson         add_last_as_label_use(l);
1549951c6300SRichard Henderson     }
1550951c6300SRichard Henderson }
1551951c6300SRichard Henderson 
155242a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1553951c6300SRichard Henderson {
155411d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
155511d11d61SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l);
155611d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
155742a268c2SRichard Henderson         tcg_gen_br(l);
1558951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
155911d11d61SRichard Henderson         tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
156011d11d61SRichard Henderson                           TCGV_LOW(arg1), TCGV_HIGH(arg1),
156111d11d61SRichard Henderson                           tcg_constant_i32(arg2),
156211d11d61SRichard Henderson                           tcg_constant_i32(arg2 >> 32),
156311d11d61SRichard Henderson                           cond, label_arg(l));
1564f85b1fc4SRichard Henderson         add_last_as_label_use(l);
1565951c6300SRichard Henderson     }
1566951c6300SRichard Henderson }
1567951c6300SRichard Henderson 
1568951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1569951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1570951c6300SRichard Henderson {
1571951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1572951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1573951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1574951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1575951c6300SRichard Henderson     } else {
15763a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1577951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1578951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1579951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1580951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15813a13c3f3SRichard Henderson         } else {
1582951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
15833a13c3f3SRichard Henderson         }
1584951c6300SRichard Henderson     }
1585951c6300SRichard Henderson }
1586951c6300SRichard Henderson 
1587951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1588951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1589951c6300SRichard Henderson {
159011d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
159111d11d61SRichard Henderson         tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2));
159211d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
159311d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 1);
159411d11d61SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
159511d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 0);
159611d11d61SRichard Henderson     } else {
159711d11d61SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
159811d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
159911d11d61SRichard Henderson                          tcg_constant_i32(arg2),
160011d11d61SRichard Henderson                          tcg_constant_i32(arg2 >> 32), cond);
160111d11d61SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
160211d11d61SRichard Henderson     }
1603951c6300SRichard Henderson }
1604951c6300SRichard Henderson 
16053635502dSRichard Henderson void tcg_gen_negsetcond_i64(TCGCond cond, TCGv_i64 ret,
16063635502dSRichard Henderson                             TCGv_i64 arg1, TCGv_i64 arg2)
16073635502dSRichard Henderson {
16083635502dSRichard Henderson     if (cond == TCG_COND_ALWAYS) {
16093635502dSRichard Henderson         tcg_gen_movi_i64(ret, -1);
16103635502dSRichard Henderson     } else if (cond == TCG_COND_NEVER) {
16113635502dSRichard Henderson         tcg_gen_movi_i64(ret, 0);
16123635502dSRichard Henderson     } else if (TCG_TARGET_HAS_negsetcond_i64) {
16133635502dSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_negsetcond_i64, ret, arg1, arg2, cond);
16143635502dSRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
16153635502dSRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
16163635502dSRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
16173635502dSRichard Henderson                          TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
16183635502dSRichard Henderson         tcg_gen_neg_i32(TCGV_LOW(ret), TCGV_LOW(ret));
16193635502dSRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_LOW(ret));
16203635502dSRichard Henderson     } else {
16213635502dSRichard Henderson         tcg_gen_setcond_i64(cond, ret, arg1, arg2);
16223635502dSRichard Henderson         tcg_gen_neg_i64(ret, ret);
16233635502dSRichard Henderson     }
16243635502dSRichard Henderson }
16253635502dSRichard Henderson 
1626951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1627951c6300SRichard Henderson {
1628b2e3ae94SRichard Henderson     if (arg2 == 0) {
1629b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1630b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1631b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1632b2e3ae94SRichard Henderson     } else {
1633f04de891SRichard Henderson         tcg_gen_mul_i64(ret, arg1, tcg_constant_i64(arg2));
1634951c6300SRichard Henderson     }
1635b2e3ae94SRichard Henderson }
1636951c6300SRichard Henderson 
1637951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1638951c6300SRichard Henderson {
1639951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1640951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1641951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16425dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1643951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1644951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1645951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1646951c6300SRichard Henderson     } else {
1647951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1648951c6300SRichard Henderson     }
1649951c6300SRichard Henderson }
1650951c6300SRichard Henderson 
1651951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1652951c6300SRichard Henderson {
1653951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1654951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1655951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
16565dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1657951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1658951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1659951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1660951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1661951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16625dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1663951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1664951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1665951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1666951c6300SRichard Henderson     } else {
1667951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1668951c6300SRichard Henderson     }
1669951c6300SRichard Henderson }
1670951c6300SRichard Henderson 
1671951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1672951c6300SRichard Henderson {
1673951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1674951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1675951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16765dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1677951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1678951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1679951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1680951c6300SRichard Henderson     } else {
1681951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1682951c6300SRichard Henderson     }
1683951c6300SRichard Henderson }
1684951c6300SRichard Henderson 
1685951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1686951c6300SRichard Henderson {
1687951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1688951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1689951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
16905dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1691951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1692951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1693951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1694951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1695951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16965dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1697951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1698951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1699951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1700951c6300SRichard Henderson     } else {
1701951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1702951c6300SRichard Henderson     }
1703951c6300SRichard Henderson }
1704951c6300SRichard Henderson 
1705951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1706951c6300SRichard Henderson {
17073a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1708951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1709951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17103a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1711951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1712951c6300SRichard Henderson     } else {
1713951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1714951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1715951c6300SRichard Henderson     }
1716951c6300SRichard Henderson }
1717951c6300SRichard Henderson 
1718951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1719951c6300SRichard Henderson {
17203a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1721951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1722951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17233a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1724951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1725951c6300SRichard Henderson     } else {
1726951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1727951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1728951c6300SRichard Henderson     }
1729951c6300SRichard Henderson }
1730951c6300SRichard Henderson 
1731951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1732951c6300SRichard Henderson {
17333a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1734951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1735951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17363a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1737951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1738951c6300SRichard Henderson     } else {
1739951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1740951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1741951c6300SRichard Henderson     }
1742951c6300SRichard Henderson }
1743951c6300SRichard Henderson 
1744951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1745951c6300SRichard Henderson {
17463a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1747951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1748951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17493a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1750951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1751951c6300SRichard Henderson     } else {
1752951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1753951c6300SRichard Henderson     }
1754951c6300SRichard Henderson }
1755951c6300SRichard Henderson 
1756951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1757951c6300SRichard Henderson {
17583a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1759951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1760951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17613a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1762951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1763951c6300SRichard Henderson     } else {
1764951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1765951c6300SRichard Henderson     }
1766951c6300SRichard Henderson }
1767951c6300SRichard Henderson 
1768951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1769951c6300SRichard Henderson {
17703a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1771951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1772951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17733a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1774951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1775951c6300SRichard Henderson     } else {
1776951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1777951c6300SRichard Henderson     }
1778951c6300SRichard Henderson }
1779951c6300SRichard Henderson 
17808b078800SPhilippe Mathieu-Daudé /*
17818b078800SPhilippe Mathieu-Daudé  * bswap16_i64: 16-bit byte swap on the low bits of a 64-bit value.
17828b078800SPhilippe Mathieu-Daudé  *
17838b078800SPhilippe Mathieu-Daudé  * Byte pattern: xxxxxxxxab -> yyyyyyyyba
17848b078800SPhilippe Mathieu-Daudé  *
17858b078800SPhilippe Mathieu-Daudé  * With TCG_BSWAP_IZ, x == zero, else undefined.
17868b078800SPhilippe Mathieu-Daudé  * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined.
17878b078800SPhilippe Mathieu-Daudé  */
17882b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1789951c6300SRichard Henderson {
17902b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17912b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17922b836c2aSRichard Henderson 
17933a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17942b836c2aSRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags);
17952b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17962b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17972b836c2aSRichard Henderson         } else {
1798951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17992b836c2aSRichard Henderson         }
18003a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
18012b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags);
1802951c6300SRichard Henderson     } else {
18035dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
18045dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
1805951c6300SRichard Henderson 
18068b078800SPhilippe Mathieu-Daudé                                             /* arg = ......ab or xxxxxxab */
18078b078800SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(t0, arg, 8);       /*  t0 = .......a or .xxxxxxa */
18082b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
18098b078800SPhilippe Mathieu-Daudé             tcg_gen_ext8u_i64(t0, t0);      /*  t0 = .......a */
18102b836c2aSRichard Henderson         }
18112b836c2aSRichard Henderson 
18122b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
18138b078800SPhilippe Mathieu-Daudé             tcg_gen_shli_i64(t1, arg, 56);  /*  t1 = b....... */
18148b078800SPhilippe Mathieu-Daudé             tcg_gen_sari_i64(t1, t1, 48);   /*  t1 = ssssssb. */
18152b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
18168b078800SPhilippe Mathieu-Daudé             tcg_gen_ext8u_i64(t1, arg);     /*  t1 = .......b */
18178b078800SPhilippe Mathieu-Daudé             tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = ......b. */
18182b836c2aSRichard Henderson         } else {
18198b078800SPhilippe Mathieu-Daudé             tcg_gen_shli_i64(t1, arg, 8);   /*  t1 = xxxxxab. */
18202b836c2aSRichard Henderson         }
18212b836c2aSRichard Henderson 
18228b078800SPhilippe Mathieu-Daudé         tcg_gen_or_i64(ret, t0, t1);        /* ret = ......ba (OZ) */
18238b078800SPhilippe Mathieu-Daudé                                             /*       ssssssba (OS) */
18248b078800SPhilippe Mathieu-Daudé                                             /*       xxxxxaba (no flag) */
1825951c6300SRichard Henderson         tcg_temp_free_i64(t0);
18262b836c2aSRichard Henderson         tcg_temp_free_i64(t1);
1827951c6300SRichard Henderson     }
1828951c6300SRichard Henderson }
1829951c6300SRichard Henderson 
18309c406215SPhilippe Mathieu-Daudé /*
18319c406215SPhilippe Mathieu-Daudé  * bswap32_i64: 32-bit byte swap on the low bits of a 64-bit value.
18329c406215SPhilippe Mathieu-Daudé  *
18339c406215SPhilippe Mathieu-Daudé  * Byte pattern: xxxxabcd -> yyyydcba
18349c406215SPhilippe Mathieu-Daudé  *
18359c406215SPhilippe Mathieu-Daudé  * With TCG_BSWAP_IZ, x == zero, else undefined.
18369c406215SPhilippe Mathieu-Daudé  * With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined.
18379c406215SPhilippe Mathieu-Daudé  */
18382b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1839951c6300SRichard Henderson {
18402b836c2aSRichard Henderson     /* Only one extension flag may be present. */
18412b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
18422b836c2aSRichard Henderson 
18433a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1844951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
18452b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
18462b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
18472b836c2aSRichard Henderson         } else {
1848951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18492b836c2aSRichard Henderson         }
18503a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
18512b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags);
1852951c6300SRichard Henderson     } else {
18535dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
18545dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
185511d11d61SRichard Henderson         TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
1856951c6300SRichard Henderson 
18572b836c2aSRichard Henderson                                             /* arg = xxxxabcd */
18582b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);       /*  t0 = .xxxxabc */
1859a686dc71SRichard Henderson         tcg_gen_and_i64(t1, arg, t2);       /*  t1 = .....b.d */
1860a686dc71SRichard Henderson         tcg_gen_and_i64(t0, t0, t2);        /*  t0 = .....a.c */
1861a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);        /*  t1 = ....b.d. */
1862a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ....badc */
1863951c6300SRichard Henderson 
1864a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, ret, 48);      /*  t1 = dc...... */
1865a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);      /*  t0 = ......ba */
18662b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
18672b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 32);   /*  t1 = ssssdc.. */
18682b836c2aSRichard Henderson         } else {
1869a686dc71SRichard Henderson             tcg_gen_shri_i64(t1, t1, 32);   /*  t1 = ....dc.. */
18702b836c2aSRichard Henderson         }
18719c406215SPhilippe Mathieu-Daudé         tcg_gen_or_i64(ret, t0, t1);        /* ret = ssssdcba (OS) */
18729c406215SPhilippe Mathieu-Daudé                                             /*       ....dcba (else) */
1873951c6300SRichard Henderson 
1874951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1875951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1876951c6300SRichard Henderson     }
1877951c6300SRichard Henderson }
1878951c6300SRichard Henderson 
187995180e75SPhilippe Mathieu-Daudé /*
188095180e75SPhilippe Mathieu-Daudé  * bswap64_i64: 64-bit byte swap on a 64-bit value.
188195180e75SPhilippe Mathieu-Daudé  *
188295180e75SPhilippe Mathieu-Daudé  * Byte pattern: abcdefgh -> hgfedcba
188395180e75SPhilippe Mathieu-Daudé  */
1884951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1885951c6300SRichard Henderson {
18863a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1887951c6300SRichard Henderson         TCGv_i32 t0, t1;
18885dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
18895dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
1890951c6300SRichard Henderson 
1891951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1892951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1893951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1894951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1895951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1896951c6300SRichard Henderson         tcg_temp_free_i32(t1);
18973a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1898587195bdSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
1899951c6300SRichard Henderson     } else {
19005dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
19015dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
19025dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
1903951c6300SRichard Henderson 
19049e821eabSRichard Henderson                                         /* arg = abcdefgh */
19059e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
19069e821eabSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .abcdefg */
19079e821eabSRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .b.d.f.h */
19089e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .a.c.e.g */
19099e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = b.d.f.h. */
19109e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = badcfehg */
1911951c6300SRichard Henderson 
19129e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
19139e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ..badcfe */
19149e821eabSRichard Henderson         tcg_gen_and_i64(t1, ret, t2);   /*  t1 = ..dc..hg */
19159e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = ..ba..fe */
19169e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 16);   /*  t1 = dc..hg.. */
19179e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = dcbahgfe */
1918951c6300SRichard Henderson 
19199e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 32);  /*  t0 = ....dcba */
19209e821eabSRichard Henderson         tcg_gen_shli_i64(t1, ret, 32);  /*  t1 = hgfe.... */
19219e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = hgfedcba */
1922951c6300SRichard Henderson 
1923951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1924951c6300SRichard Henderson         tcg_temp_free_i64(t1);
19259e821eabSRichard Henderson         tcg_temp_free_i64(t2);
1926951c6300SRichard Henderson     }
1927951c6300SRichard Henderson }
1928951c6300SRichard Henderson 
1929*b8976aa5SPhilippe Mathieu-Daudé /*
1930*b8976aa5SPhilippe Mathieu-Daudé  * hswap_i64: Swap 16-bit halfwords within a 64-bit value.
1931*b8976aa5SPhilippe Mathieu-Daudé  * See also include/qemu/bitops.h, hswap64.
1932*b8976aa5SPhilippe Mathieu-Daudé  *
1933*b8976aa5SPhilippe Mathieu-Daudé  * Byte pattern: abcdefgh -> ghefcdab
1934*b8976aa5SPhilippe Mathieu-Daudé  */
193546be8425SRichard Henderson void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg)
193646be8425SRichard Henderson {
193746be8425SRichard Henderson     uint64_t m = 0x0000ffff0000ffffull;
19385dd48602SRichard Henderson     TCGv_i64 t0 = tcg_temp_ebb_new_i64();
19395dd48602SRichard Henderson     TCGv_i64 t1 = tcg_temp_ebb_new_i64();
194046be8425SRichard Henderson 
1941*b8976aa5SPhilippe Mathieu-Daudé                                         /* arg = abcdefgh */
1942*b8976aa5SPhilippe Mathieu-Daudé     tcg_gen_rotli_i64(t1, arg, 32);     /*  t1 = efghabcd */
1943*b8976aa5SPhilippe Mathieu-Daudé     tcg_gen_andi_i64(t0, t1, m);        /*  t0 = ..gh..cd */
1944*b8976aa5SPhilippe Mathieu-Daudé     tcg_gen_shli_i64(t0, t0, 16);       /*  t0 = gh..cd.. */
1945*b8976aa5SPhilippe Mathieu-Daudé     tcg_gen_shri_i64(t1, t1, 16);       /*  t1 = ..efghab */
1946*b8976aa5SPhilippe Mathieu-Daudé     tcg_gen_andi_i64(t1, t1, m);        /*  t1 = ..ef..ab */
1947*b8976aa5SPhilippe Mathieu-Daudé     tcg_gen_or_i64(ret, t0, t1);        /* ret = ghefcdab */
194846be8425SRichard Henderson 
194946be8425SRichard Henderson     tcg_temp_free_i64(t0);
195046be8425SRichard Henderson     tcg_temp_free_i64(t1);
195146be8425SRichard Henderson }
195246be8425SRichard Henderson 
195346be8425SRichard Henderson void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg)
195446be8425SRichard Henderson {
195546be8425SRichard Henderson     /* Swapping 2 32-bit elements is a rotate. */
195646be8425SRichard Henderson     tcg_gen_rotli_i64(ret, arg, 32);
195746be8425SRichard Henderson }
195846be8425SRichard Henderson 
1959951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1960951c6300SRichard Henderson {
19613a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19623a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
19633a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
19643a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1965951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1966951c6300SRichard Henderson     } else {
1967951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1968951c6300SRichard Henderson     }
1969951c6300SRichard Henderson }
1970951c6300SRichard Henderson 
1971951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1972951c6300SRichard Henderson {
19733a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19743a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19753a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19763a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1977951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1978951c6300SRichard Henderson     } else {
19795dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1980951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1981951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1982951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1983951c6300SRichard Henderson     }
1984951c6300SRichard Henderson }
1985951c6300SRichard Henderson 
1986951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1987951c6300SRichard Henderson {
19883a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19893a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19903a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19913a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1992951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1993951c6300SRichard Henderson     } else {
1994951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1995951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1996951c6300SRichard Henderson     }
1997951c6300SRichard Henderson }
1998951c6300SRichard Henderson 
1999951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2000951c6300SRichard Henderson {
20013a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
20023a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
20033a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
20043a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
2005951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
2006951c6300SRichard Henderson     } else {
2007951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
2008951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
2009951c6300SRichard Henderson     }
2010951c6300SRichard Henderson }
2011951c6300SRichard Henderson 
2012951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2013951c6300SRichard Henderson {
20143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
20153a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
20163a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
20173a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
2018951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
2019951c6300SRichard Henderson     } else {
2020951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
2021951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
2022951c6300SRichard Henderson     }
2023951c6300SRichard Henderson }
2024951c6300SRichard Henderson 
2025951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2026951c6300SRichard Henderson {
20273a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
20283a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
20293a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
20303a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
2031951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
2032951c6300SRichard Henderson     } else {
20335dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2034951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
2035951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
2036951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2037951c6300SRichard Henderson     }
2038951c6300SRichard Henderson }
2039951c6300SRichard Henderson 
20400e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
20410e28d006SRichard Henderson {
20420e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
20430e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
20440e28d006SRichard Henderson     } else {
20450e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
20460e28d006SRichard Henderson     }
20470e28d006SRichard Henderson }
20480e28d006SRichard Henderson 
20490e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
20500e28d006SRichard Henderson {
20510e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
20520e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
20530e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
20545dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
205511d11d61SRichard Henderson         tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32);
20560e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
20570e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
20580e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
20590e28d006SRichard Henderson         tcg_temp_free_i32(t);
20600e28d006SRichard Henderson     } else {
2061f04de891SRichard Henderson         tcg_gen_clz_i64(ret, arg1, tcg_constant_i64(arg2));
20620e28d006SRichard Henderson     }
20630e28d006SRichard Henderson }
20640e28d006SRichard Henderson 
20650e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
20660e28d006SRichard Henderson {
20670e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
20680e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
206914e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
20705dd48602SRichard Henderson         TCGv_i64 z, t = tcg_temp_ebb_new_i64();
207114e99210SRichard Henderson 
207214e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
207314e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
207414e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
207514e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
207614e99210SRichard Henderson         } else {
207714e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
207814e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
207914e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
208014e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
208114e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
208214e99210SRichard Henderson         }
208311d11d61SRichard Henderson         z = tcg_constant_i64(0);
208414e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
208514e99210SRichard Henderson         tcg_temp_free_i64(t);
208614e99210SRichard Henderson         tcg_temp_free_i64(z);
20870e28d006SRichard Henderson     } else {
20880e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
20890e28d006SRichard Henderson     }
20900e28d006SRichard Henderson }
20910e28d006SRichard Henderson 
20920e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
20930e28d006SRichard Henderson {
20940e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
20950e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
20960e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
20975dd48602SRichard Henderson         TCGv_i32 t32 = tcg_temp_ebb_new_i32();
209811d11d61SRichard Henderson         tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32);
20990e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
21000e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
21010e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21020e28d006SRichard Henderson         tcg_temp_free_i32(t32);
210314e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
210414e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
210514e99210SRichard Henderson                && arg2 == 64) {
210614e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
21075dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
210814e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
210914e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
211014e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
211114e99210SRichard Henderson         tcg_temp_free_i64(t);
21120e28d006SRichard Henderson     } else {
2113f04de891SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, tcg_constant_i64(arg2));
21140e28d006SRichard Henderson     }
21150e28d006SRichard Henderson }
21160e28d006SRichard Henderson 
2117086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
2118086920c2SRichard Henderson {
2119086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
21205dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2121086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
2122086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
2123086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
2124086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
2125086920c2SRichard Henderson         tcg_temp_free_i64(t);
2126086920c2SRichard Henderson     } else {
2127086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
2128086920c2SRichard Henderson     }
2129086920c2SRichard Henderson }
2130086920c2SRichard Henderson 
2131a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
2132a768e4e9SRichard Henderson {
2133a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
2134a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
2135a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
2136a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2137a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2138a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
2139a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
2140a768e4e9SRichard Henderson     } else {
2141a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
2142a768e4e9SRichard Henderson     }
2143a768e4e9SRichard Henderson }
2144a768e4e9SRichard Henderson 
2145951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2146951c6300SRichard Henderson {
2147951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2148951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
2149951c6300SRichard Henderson     } else {
2150951c6300SRichard Henderson         TCGv_i64 t0, t1;
21515dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i64();
21525dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i64();
2153951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
2154951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2155951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
2156951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2157951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2158951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2159951c6300SRichard Henderson     }
2160951c6300SRichard Henderson }
2161951c6300SRichard Henderson 
216207dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2163951c6300SRichard Henderson {
216407dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2165951c6300SRichard Henderson     /* some cases can be optimized here */
2166951c6300SRichard Henderson     if (arg2 == 0) {
2167951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2168951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
216911d11d61SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2));
2170951c6300SRichard Henderson     } else {
2171951c6300SRichard Henderson         TCGv_i64 t0, t1;
21725dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i64();
21735dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i64();
2174951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
2175951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
2176951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2177951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2178951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2179951c6300SRichard Henderson     }
2180951c6300SRichard Henderson }
2181951c6300SRichard Henderson 
2182951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2183951c6300SRichard Henderson {
2184951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2185951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
2186951c6300SRichard Henderson     } else {
2187951c6300SRichard Henderson         TCGv_i64 t0, t1;
21885dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i64();
21895dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i64();
2190951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
2191951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2192951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
2193951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2194951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2195951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2196951c6300SRichard Henderson     }
2197951c6300SRichard Henderson }
2198951c6300SRichard Henderson 
219907dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2200951c6300SRichard Henderson {
220107dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2202951c6300SRichard Henderson     /* some cases can be optimized here */
2203951c6300SRichard Henderson     if (arg2 == 0) {
2204951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2205951c6300SRichard Henderson     } else {
2206951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
2207951c6300SRichard Henderson     }
2208951c6300SRichard Henderson }
2209951c6300SRichard Henderson 
2210951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
2211951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
2212951c6300SRichard Henderson {
2213951c6300SRichard Henderson     uint64_t mask;
2214951c6300SRichard Henderson     TCGv_i64 t1;
2215951c6300SRichard Henderson 
2216951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
22170d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2218951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2219951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2220951c6300SRichard Henderson 
22210d0d309dSRichard Henderson     if (len == 64) {
2222951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2223951c6300SRichard Henderson         return;
2224951c6300SRichard Henderson     }
2225951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2226951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2227951c6300SRichard Henderson         return;
2228951c6300SRichard Henderson     }
2229951c6300SRichard Henderson 
22303a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2231951c6300SRichard Henderson         if (ofs >= 32) {
2232951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2233951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2234951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2235951c6300SRichard Henderson             return;
2236951c6300SRichard Henderson         }
2237951c6300SRichard Henderson         if (ofs + len <= 32) {
2238951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2239951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2240951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2241951c6300SRichard Henderson             return;
2242951c6300SRichard Henderson         }
22433a13c3f3SRichard Henderson     }
2244951c6300SRichard Henderson 
22455dd48602SRichard Henderson     t1 = tcg_temp_ebb_new_i64();
2246951c6300SRichard Henderson 
2247b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i64) {
2248b0a60567SRichard Henderson         if (ofs + len == 64) {
2249b0a60567SRichard Henderson             tcg_gen_shli_i64(t1, arg1, len);
2250b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, t1, arg2, len);
2251b0a60567SRichard Henderson             goto done;
2252b0a60567SRichard Henderson         }
2253b0a60567SRichard Henderson         if (ofs == 0) {
2254b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, arg1, arg2, len);
2255b0a60567SRichard Henderson             tcg_gen_rotli_i64(ret, ret, len);
2256b0a60567SRichard Henderson             goto done;
2257b0a60567SRichard Henderson         }
2258b0a60567SRichard Henderson     }
2259b0a60567SRichard Henderson 
2260b0a60567SRichard Henderson     mask = (1ull << len) - 1;
2261951c6300SRichard Henderson     if (ofs + len < 64) {
2262951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2263951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2264951c6300SRichard Henderson     } else {
2265951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2266951c6300SRichard Henderson     }
2267951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2268951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2269b0a60567SRichard Henderson  done:
2270951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2271951c6300SRichard Henderson }
2272951c6300SRichard Henderson 
227307cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
227407cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
227507cc68d5SRichard Henderson {
227607cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
227707cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
227807cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
227907cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
228007cc68d5SRichard Henderson 
228107cc68d5SRichard Henderson     if (ofs + len == 64) {
228207cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
228307cc68d5SRichard Henderson     } else if (ofs == 0) {
228407cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
228507cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
228607cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
228711d11d61SRichard Henderson         TCGv_i64 zero = tcg_constant_i64(0);
228807cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
228907cc68d5SRichard Henderson     } else {
229007cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
229107cc68d5SRichard Henderson             if (ofs >= 32) {
229207cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
229307cc68d5SRichard Henderson                                       ofs - 32, len);
229407cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
229507cc68d5SRichard Henderson                 return;
229607cc68d5SRichard Henderson             }
229707cc68d5SRichard Henderson             if (ofs + len <= 32) {
229807cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
229907cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
230007cc68d5SRichard Henderson                 return;
230107cc68d5SRichard Henderson             }
230207cc68d5SRichard Henderson         }
230307cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
230407cc68d5SRichard Henderson            which allows ARG to stay live.  */
230507cc68d5SRichard Henderson         switch (len) {
230607cc68d5SRichard Henderson         case 32:
230707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
230807cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
230907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
231007cc68d5SRichard Henderson                 return;
231107cc68d5SRichard Henderson             }
231207cc68d5SRichard Henderson             break;
231307cc68d5SRichard Henderson         case 16:
231407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
231507cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
231607cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
231707cc68d5SRichard Henderson                 return;
231807cc68d5SRichard Henderson             }
231907cc68d5SRichard Henderson             break;
232007cc68d5SRichard Henderson         case 8:
232107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
232207cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
232307cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
232407cc68d5SRichard Henderson                 return;
232507cc68d5SRichard Henderson             }
232607cc68d5SRichard Henderson             break;
232707cc68d5SRichard Henderson         }
232807cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
232907cc68d5SRichard Henderson         switch (ofs + len) {
233007cc68d5SRichard Henderson         case 32:
233107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
233207cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
233307cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
233407cc68d5SRichard Henderson                 return;
233507cc68d5SRichard Henderson             }
233607cc68d5SRichard Henderson             break;
233707cc68d5SRichard Henderson         case 16:
233807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
233907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
234007cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
234107cc68d5SRichard Henderson                 return;
234207cc68d5SRichard Henderson             }
234307cc68d5SRichard Henderson             break;
234407cc68d5SRichard Henderson         case 8:
234507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
234607cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
234707cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
234807cc68d5SRichard Henderson                 return;
234907cc68d5SRichard Henderson             }
235007cc68d5SRichard Henderson             break;
235107cc68d5SRichard Henderson         }
235207cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
235307cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
235407cc68d5SRichard Henderson     }
235507cc68d5SRichard Henderson }
235607cc68d5SRichard Henderson 
23577ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
23587ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
23597ec8bab3SRichard Henderson {
23607ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
23617ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
23627ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
23637ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
23647ec8bab3SRichard Henderson 
23657ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
23667ec8bab3SRichard Henderson     if (ofs + len == 64) {
23677ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
23687ec8bab3SRichard Henderson         return;
23697ec8bab3SRichard Henderson     }
23707ec8bab3SRichard Henderson     if (ofs == 0) {
23717ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
23727ec8bab3SRichard Henderson         return;
23737ec8bab3SRichard Henderson     }
23747ec8bab3SRichard Henderson 
23757ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
23767ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
23777ec8bab3SRichard Henderson         if (ofs >= 32) {
23787ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
23797ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
23807ec8bab3SRichard Henderson             return;
23817ec8bab3SRichard Henderson         }
23827ec8bab3SRichard Henderson         if (ofs + len <= 32) {
23837ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
23847ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
23857ec8bab3SRichard Henderson             return;
23867ec8bab3SRichard Henderson         }
23877ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
23887ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
23897ec8bab3SRichard Henderson         goto do_shift_and;
23907ec8bab3SRichard Henderson     }
23917ec8bab3SRichard Henderson 
23927ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
23937ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
23947ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
23957ec8bab3SRichard Henderson         return;
23967ec8bab3SRichard Henderson     }
23977ec8bab3SRichard Henderson 
23987ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
23997ec8bab3SRichard Henderson     switch (ofs + len) {
24007ec8bab3SRichard Henderson     case 32:
24017ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
24027ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
24037ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
24047ec8bab3SRichard Henderson             return;
24057ec8bab3SRichard Henderson         }
24067ec8bab3SRichard Henderson         break;
24077ec8bab3SRichard Henderson     case 16:
24087ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
24097ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
24107ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
24117ec8bab3SRichard Henderson             return;
24127ec8bab3SRichard Henderson         }
24137ec8bab3SRichard Henderson         break;
24147ec8bab3SRichard Henderson     case 8:
24157ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
24167ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
24177ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
24187ec8bab3SRichard Henderson             return;
24197ec8bab3SRichard Henderson         }
24207ec8bab3SRichard Henderson         break;
24217ec8bab3SRichard Henderson     }
24227ec8bab3SRichard Henderson 
24237ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
24247ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
24257ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
24267ec8bab3SRichard Henderson     switch (len) {
24277ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
24287ec8bab3SRichard Henderson     do_shift_and:
24297ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
24307ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
24317ec8bab3SRichard Henderson         break;
24327ec8bab3SRichard Henderson     default:
24337ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
24347ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
24357ec8bab3SRichard Henderson         break;
24367ec8bab3SRichard Henderson     }
24377ec8bab3SRichard Henderson }
24387ec8bab3SRichard Henderson 
24397ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
24407ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
24417ec8bab3SRichard Henderson {
24427ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
24437ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
24447ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
24457ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
24467ec8bab3SRichard Henderson 
24477ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
24487ec8bab3SRichard Henderson     if (ofs + len == 64) {
24497ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
24507ec8bab3SRichard Henderson         return;
24517ec8bab3SRichard Henderson     }
24527ec8bab3SRichard Henderson     if (ofs == 0) {
24537ec8bab3SRichard Henderson         switch (len) {
24547ec8bab3SRichard Henderson         case 32:
24557ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
24567ec8bab3SRichard Henderson             return;
24577ec8bab3SRichard Henderson         case 16:
24587ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
24597ec8bab3SRichard Henderson             return;
24607ec8bab3SRichard Henderson         case 8:
24617ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
24627ec8bab3SRichard Henderson             return;
24637ec8bab3SRichard Henderson         }
24647ec8bab3SRichard Henderson     }
24657ec8bab3SRichard Henderson 
24667ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
24677ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
24687ec8bab3SRichard Henderson         if (ofs >= 32) {
24697ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
24707ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
24717ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
24727ec8bab3SRichard Henderson         } else if (ofs == 0) {
24737ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
24747ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
24757ec8bab3SRichard Henderson             return;
24767ec8bab3SRichard Henderson         } else if (len > 32) {
24775dd48602SRichard Henderson             TCGv_i32 t = tcg_temp_ebb_new_i32();
24787ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
24797ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
24807ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
24817ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24827ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
24837ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
24847ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
24857ec8bab3SRichard Henderson             return;
24867ec8bab3SRichard Henderson         } else {
24877ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
24887ec8bab3SRichard Henderson                field sits at the MSB.  */
24897ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
24907ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
24917ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
24927ec8bab3SRichard Henderson         }
24937ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
24947ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
24957ec8bab3SRichard Henderson         return;
24967ec8bab3SRichard Henderson     }
24977ec8bab3SRichard Henderson 
24987ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
24997ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
25007ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
25017ec8bab3SRichard Henderson         return;
25027ec8bab3SRichard Henderson     }
25037ec8bab3SRichard Henderson 
25047ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
25057ec8bab3SRichard Henderson     switch (ofs + len) {
25067ec8bab3SRichard Henderson     case 32:
25077ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
25087ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
25097ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
25107ec8bab3SRichard Henderson             return;
25117ec8bab3SRichard Henderson         }
25127ec8bab3SRichard Henderson         break;
25137ec8bab3SRichard Henderson     case 16:
25147ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
25157ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
25167ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
25177ec8bab3SRichard Henderson             return;
25187ec8bab3SRichard Henderson         }
25197ec8bab3SRichard Henderson         break;
25207ec8bab3SRichard Henderson     case 8:
25217ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
25227ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
25237ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
25247ec8bab3SRichard Henderson             return;
25257ec8bab3SRichard Henderson         }
25267ec8bab3SRichard Henderson         break;
25277ec8bab3SRichard Henderson     }
25287ec8bab3SRichard Henderson     switch (len) {
25297ec8bab3SRichard Henderson     case 32:
25307ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
25317ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
25327ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
25337ec8bab3SRichard Henderson             return;
25347ec8bab3SRichard Henderson         }
25357ec8bab3SRichard Henderson         break;
25367ec8bab3SRichard Henderson     case 16:
25377ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
25387ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
25397ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
25407ec8bab3SRichard Henderson             return;
25417ec8bab3SRichard Henderson         }
25427ec8bab3SRichard Henderson         break;
25437ec8bab3SRichard Henderson     case 8:
25447ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
25457ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
25467ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
25477ec8bab3SRichard Henderson             return;
25487ec8bab3SRichard Henderson         }
25497ec8bab3SRichard Henderson         break;
25507ec8bab3SRichard Henderson     }
25517ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
25527ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
25537ec8bab3SRichard Henderson }
25547ec8bab3SRichard Henderson 
25552089fcc9SDavid Hildenbrand /*
25562089fcc9SDavid Hildenbrand  * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
25572089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
25582089fcc9SDavid Hildenbrand  */
25592089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
25602089fcc9SDavid Hildenbrand                           unsigned int ofs)
25612089fcc9SDavid Hildenbrand {
25622089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 64);
25632089fcc9SDavid Hildenbrand     if (ofs == 0) {
25642089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, al);
25652089fcc9SDavid Hildenbrand     } else if (ofs == 64) {
25662089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, ah);
25672089fcc9SDavid Hildenbrand     } else if (al == ah) {
25682089fcc9SDavid Hildenbrand         tcg_gen_rotri_i64(ret, al, ofs);
2569fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i64) {
2570fce1296fSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
25712089fcc9SDavid Hildenbrand     } else {
25725dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
25732089fcc9SDavid Hildenbrand         tcg_gen_shri_i64(t0, al, ofs);
25742089fcc9SDavid Hildenbrand         tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs);
25752089fcc9SDavid Hildenbrand         tcg_temp_free_i64(t0);
25762089fcc9SDavid Hildenbrand     }
25772089fcc9SDavid Hildenbrand }
25782089fcc9SDavid Hildenbrand 
2579951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2580951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2581951c6300SRichard Henderson {
258237ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
258337ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
258437ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
258537ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
258637ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
25875dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
25885dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
2589951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2590951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2591951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2592951c6300SRichard Henderson 
2593951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2594951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2595951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2596951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2597951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2598951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2599951c6300SRichard Henderson         } else {
2600951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2601951c6300SRichard Henderson 
2602951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2603951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2604951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2605951c6300SRichard Henderson 
2606951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2607951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2608951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2609951c6300SRichard Henderson         }
2610951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2611951c6300SRichard Henderson         tcg_temp_free_i32(t1);
26123a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2613951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2614951c6300SRichard Henderson     } else {
26155dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
26165dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
26174a883870SRichard Henderson         tcg_gen_negsetcond_i64(cond, t0, c1, c2);
2618951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2619951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2620951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2621951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2622951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2623951c6300SRichard Henderson     }
2624951c6300SRichard Henderson }
2625951c6300SRichard Henderson 
2626951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2627951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2628951c6300SRichard Henderson {
2629951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2630951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2631951c6300SRichard Henderson     } else {
26325dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
26335dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2634951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2635951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2636951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2637951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2638951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2639951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2640951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2641951c6300SRichard Henderson     }
2642951c6300SRichard Henderson }
2643951c6300SRichard Henderson 
2644951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2645951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2646951c6300SRichard Henderson {
2647951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2648951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2649951c6300SRichard Henderson     } else {
26505dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
26515dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2652951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2653951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2654951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2655951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2656951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2657951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2658951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2659951c6300SRichard Henderson     }
2660951c6300SRichard Henderson }
2661951c6300SRichard Henderson 
2662951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2663951c6300SRichard Henderson {
2664951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2665951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2666951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
26675dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2668951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2669951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2670951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2671951c6300SRichard Henderson         tcg_temp_free_i64(t);
2672951c6300SRichard Henderson     } else {
26735dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2674951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2675951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2676951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2677951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2678951c6300SRichard Henderson     }
2679951c6300SRichard Henderson }
2680951c6300SRichard Henderson 
2681951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2682951c6300SRichard Henderson {
2683951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2684951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2685951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
26865dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2687951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2688951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2689951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2690951c6300SRichard Henderson         tcg_temp_free_i64(t);
2691951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
26925dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
26935dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
26945dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
26955dd48602SRichard Henderson         TCGv_i64 t3 = tcg_temp_ebb_new_i64();
2696951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2697951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2698951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2699951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2700951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2701951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2702951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2703951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2704951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2705951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2706951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2707951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2708951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2709951c6300SRichard Henderson     } else {
27105dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2711951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2712951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2713951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2714951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2715951c6300SRichard Henderson     }
2716951c6300SRichard Henderson }
2717951c6300SRichard Henderson 
27185087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
27195087abfbSRichard Henderson {
27205dd48602SRichard Henderson     TCGv_i64 t0 = tcg_temp_ebb_new_i64();
27215dd48602SRichard Henderson     TCGv_i64 t1 = tcg_temp_ebb_new_i64();
27225dd48602SRichard Henderson     TCGv_i64 t2 = tcg_temp_ebb_new_i64();
27235087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
27245087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
27255087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
27265087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
27275087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
27285087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
27295087abfbSRichard Henderson     tcg_temp_free_i64(t0);
27305087abfbSRichard Henderson     tcg_temp_free_i64(t1);
27315087abfbSRichard Henderson     tcg_temp_free_i64(t2);
27325087abfbSRichard Henderson }
27335087abfbSRichard Henderson 
2734b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2735b87fb8cdSRichard Henderson {
2736b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2737b87fb8cdSRichard Henderson }
2738b87fb8cdSRichard Henderson 
2739b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2740b87fb8cdSRichard Henderson {
2741b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2742b87fb8cdSRichard Henderson }
2743b87fb8cdSRichard Henderson 
2744b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2745b87fb8cdSRichard Henderson {
2746b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2747b87fb8cdSRichard Henderson }
2748b87fb8cdSRichard Henderson 
2749b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2750b87fb8cdSRichard Henderson {
2751b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2752b87fb8cdSRichard Henderson }
2753b87fb8cdSRichard Henderson 
2754ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
2755ff1f11f7SRichard Henderson {
27565dd48602SRichard Henderson     TCGv_i64 t = tcg_temp_ebb_new_i64();
2757ff1f11f7SRichard Henderson 
2758ff1f11f7SRichard Henderson     tcg_gen_sari_i64(t, a, 63);
2759ff1f11f7SRichard Henderson     tcg_gen_xor_i64(ret, a, t);
2760ff1f11f7SRichard Henderson     tcg_gen_sub_i64(ret, ret, t);
2761ff1f11f7SRichard Henderson     tcg_temp_free_i64(t);
2762ff1f11f7SRichard Henderson }
2763ff1f11f7SRichard Henderson 
2764951c6300SRichard Henderson /* Size changing operations.  */
2765951c6300SRichard Henderson 
2766609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2767951c6300SRichard Henderson {
27683a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2769951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
277013d885b0SRichard Henderson     } else if (TCG_TARGET_HAS_extr_i64_i32) {
2771b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2772ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2773951c6300SRichard Henderson     } else {
2774dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2775609ad705SRichard Henderson     }
2776609ad705SRichard Henderson }
2777609ad705SRichard Henderson 
2778609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2779609ad705SRichard Henderson {
2780609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2781609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
278213d885b0SRichard Henderson     } else if (TCG_TARGET_HAS_extr_i64_i32) {
2783b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2784ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2785951c6300SRichard Henderson     } else {
27865dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2787609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2788dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2789951c6300SRichard Henderson         tcg_temp_free_i64(t);
2790951c6300SRichard Henderson     }
2791951c6300SRichard Henderson }
2792951c6300SRichard Henderson 
2793951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2794951c6300SRichard Henderson {
27953a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2796951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2797951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
27983a13c3f3SRichard Henderson     } else {
2799b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2800ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
28013a13c3f3SRichard Henderson     }
2802951c6300SRichard Henderson }
2803951c6300SRichard Henderson 
2804951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2805951c6300SRichard Henderson {
28063a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2807951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2808951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
28093a13c3f3SRichard Henderson     } else {
2810b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2811ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
28123a13c3f3SRichard Henderson     }
2813951c6300SRichard Henderson }
2814951c6300SRichard Henderson 
2815951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2816951c6300SRichard Henderson {
28173a13c3f3SRichard Henderson     TCGv_i64 tmp;
28183a13c3f3SRichard Henderson 
28193a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2820951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2821951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
28223a13c3f3SRichard Henderson         return;
28233a13c3f3SRichard Henderson     }
28243a13c3f3SRichard Henderson 
28255dd48602SRichard Henderson     tmp = tcg_temp_ebb_new_i64();
2826951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2827951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2828951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2829951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2830951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2831951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2832951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2833951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2834951c6300SRichard Henderson     } else {
2835951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2836951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2837951c6300SRichard Henderson     }
2838951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2839951c6300SRichard Henderson }
2840951c6300SRichard Henderson 
2841951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2842951c6300SRichard Henderson {
28433a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2844951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2845951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
28463a13c3f3SRichard Henderson     } else {
2847609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2848609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
28493a13c3f3SRichard Henderson     }
2850951c6300SRichard Henderson }
2851951c6300SRichard Henderson 
2852951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2853951c6300SRichard Henderson {
2854951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2855951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2856951c6300SRichard Henderson }
2857951c6300SRichard Henderson 
28584771e71cSRichard Henderson void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg)
28594771e71cSRichard Henderson {
28604771e71cSRichard Henderson     tcg_gen_mov_i64(lo, TCGV128_LOW(arg));
28614771e71cSRichard Henderson     tcg_gen_mov_i64(hi, TCGV128_HIGH(arg));
28624771e71cSRichard Henderson }
28634771e71cSRichard Henderson 
28644771e71cSRichard Henderson void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi)
28654771e71cSRichard Henderson {
28664771e71cSRichard Henderson     tcg_gen_mov_i64(TCGV128_LOW(ret), lo);
28674771e71cSRichard Henderson     tcg_gen_mov_i64(TCGV128_HIGH(ret), hi);
28684771e71cSRichard Henderson }
28694771e71cSRichard Henderson 
28704771e71cSRichard Henderson void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src)
28714771e71cSRichard Henderson {
28724771e71cSRichard Henderson     if (dst != src) {
28734771e71cSRichard Henderson         tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src));
28744771e71cSRichard Henderson         tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src));
28754771e71cSRichard Henderson     }
28764771e71cSRichard Henderson }
28774771e71cSRichard Henderson 
2878951c6300SRichard Henderson /* QEMU specific operations.  */
2879951c6300SRichard Henderson 
2880d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
288107ea28b4SRichard Henderson {
2882eba40358SRichard Henderson     /*
2883eba40358SRichard Henderson      * Let the jit code return the read-only version of the
2884eba40358SRichard Henderson      * TranslationBlock, so that we minimize the pc-relative
2885eba40358SRichard Henderson      * distance of the address of the exit_tb code to TB.
2886eba40358SRichard Henderson      * This will improve utilization of pc-relative address loads.
2887eba40358SRichard Henderson      *
2888eba40358SRichard Henderson      * TODO: Move this to translator_loop, so that all const
2889eba40358SRichard Henderson      * TranslationBlock pointers refer to read-only memory.
2890eba40358SRichard Henderson      * This requires coordination with targets that do not use
2891eba40358SRichard Henderson      * the translator_loop.
2892eba40358SRichard Henderson      */
2893eba40358SRichard Henderson     uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx;
289407ea28b4SRichard Henderson 
289507ea28b4SRichard Henderson     if (tb == NULL) {
289607ea28b4SRichard Henderson         tcg_debug_assert(idx == 0);
289707ea28b4SRichard Henderson     } else if (idx <= TB_EXIT_IDXMAX) {
289807ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG
289907ea28b4SRichard Henderson         /* This is an exit following a goto_tb.  Verify that we have
290007ea28b4SRichard Henderson            seen this numbered exit before, via tcg_gen_goto_tb.  */
290107ea28b4SRichard Henderson         tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
290207ea28b4SRichard Henderson #endif
290307ea28b4SRichard Henderson     } else {
290407ea28b4SRichard Henderson         /* This is an exit via the exitreq label.  */
290507ea28b4SRichard Henderson         tcg_debug_assert(idx == TB_EXIT_REQUESTED);
290607ea28b4SRichard Henderson     }
290707ea28b4SRichard Henderson 
290807ea28b4SRichard Henderson     tcg_gen_op1i(INDEX_op_exit_tb, val);
290907ea28b4SRichard Henderson }
291007ea28b4SRichard Henderson 
2911951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2912951c6300SRichard Henderson {
291384f15616SRichard Henderson     /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
2914b7e4afbdSRichard Henderson     tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB));
2915951c6300SRichard Henderson     /* We only support two chained exits.  */
291607ea28b4SRichard Henderson     tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
2917951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2918a4761232SPhilippe Mathieu-Daudé     /* Verify that we haven't seen this numbered exit before.  */
2919b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2920b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2921951c6300SRichard Henderson #endif
2922e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2923951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2924951c6300SRichard Henderson }
2925951c6300SRichard Henderson 
29267f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2927cedbcb01SEmilio G. Cota {
2928e6d86bedSEmilio G. Cota     TCGv_ptr ptr;
2929e6d86bedSEmilio G. Cota 
2930b7e4afbdSRichard Henderson     if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) {
293184f15616SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
293284f15616SRichard Henderson         return;
293384f15616SRichard Henderson     }
293484f15616SRichard Henderson 
2935e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
29365dd48602SRichard Henderson     ptr = tcg_temp_ebb_new_ptr();
29371c2adb95SRichard Henderson     gen_helper_lookup_tb_ptr(ptr, cpu_env);
2938ae8b75dcSRichard Henderson     tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2939cedbcb01SEmilio G. Cota     tcg_temp_free_ptr(ptr);
2940cedbcb01SEmilio G. Cota }
2941