xref: /openbmc/qemu/tcg/tcg-op.c (revision c914d46d)
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 {
105*c914d46dSRichard Henderson #ifdef CONFIG_USER_ONLY
106*c914d46dSRichard Henderson     bool parallel = tcg_ctx->gen_tb->cflags & CF_PARALLEL;
107*c914d46dSRichard Henderson #else
108*c914d46dSRichard Henderson     /*
109*c914d46dSRichard Henderson      * It is tempting to elide the barrier in a uniprocessor context.
110*c914d46dSRichard Henderson      * However, even with a single cpu we have i/o threads running in
111*c914d46dSRichard Henderson      * parallel, and lack of memory order can result in e.g. virtio
112*c914d46dSRichard Henderson      * queue entries being read incorrectly.
113*c914d46dSRichard Henderson      */
114*c914d46dSRichard Henderson     bool parallel = true;
115*c914d46dSRichard Henderson #endif
116*c914d46dSRichard Henderson 
117*c914d46dSRichard 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 
279951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
280951c6300SRichard Henderson {
281b2e3ae94SRichard Henderson     if (arg2 == 0) {
282b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
283b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
284b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
285b2e3ae94SRichard Henderson     } else {
28611d11d61SRichard Henderson         tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2));
287951c6300SRichard Henderson     }
288b2e3ae94SRichard Henderson }
289951c6300SRichard Henderson 
290951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
291951c6300SRichard Henderson {
292951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
293951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
294951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
2955dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
296951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
297951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
298951c6300SRichard Henderson         tcg_temp_free_i32(t0);
299951c6300SRichard Henderson     } else {
300951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
301951c6300SRichard Henderson     }
302951c6300SRichard Henderson }
303951c6300SRichard Henderson 
304951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
305951c6300SRichard Henderson {
306951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
307951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
308951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
3095dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
310951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
311951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
312951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
313951c6300SRichard Henderson         tcg_temp_free_i32(t0);
314951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3155dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
316951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
317951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
318951c6300SRichard Henderson         tcg_temp_free_i32(t0);
319951c6300SRichard Henderson     } else {
320951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
321951c6300SRichard Henderson     }
322951c6300SRichard Henderson }
323951c6300SRichard Henderson 
324951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
325951c6300SRichard Henderson {
326951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
327951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
328951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3295dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
330951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
331951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
332951c6300SRichard Henderson         tcg_temp_free_i32(t0);
333951c6300SRichard Henderson     } else {
334951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
335951c6300SRichard Henderson     }
336951c6300SRichard Henderson }
337951c6300SRichard Henderson 
338951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
339951c6300SRichard Henderson {
340951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
341951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
342951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
3435dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
344951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
345951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
346951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
347951c6300SRichard Henderson         tcg_temp_free_i32(t0);
348951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
3495dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
350951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
351951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
352951c6300SRichard Henderson         tcg_temp_free_i32(t0);
353951c6300SRichard Henderson     } else {
354951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
355951c6300SRichard Henderson     }
356951c6300SRichard Henderson }
357951c6300SRichard Henderson 
358951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
359951c6300SRichard Henderson {
360951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
361951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
362951c6300SRichard Henderson     } else {
3635dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
364951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
365951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
366951c6300SRichard Henderson         tcg_temp_free_i32(t0);
367951c6300SRichard Henderson     }
368951c6300SRichard Henderson }
369951c6300SRichard Henderson 
370951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
371951c6300SRichard Henderson {
372951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
373951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
374951c6300SRichard Henderson     } else {
375951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
376951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
377951c6300SRichard Henderson     }
378951c6300SRichard Henderson }
379951c6300SRichard Henderson 
380951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
381951c6300SRichard Henderson {
382951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
383951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
384951c6300SRichard Henderson     } else {
385951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
386951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
387951c6300SRichard Henderson     }
388951c6300SRichard Henderson }
389951c6300SRichard Henderson 
390951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
391951c6300SRichard Henderson {
392951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
393951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
394951c6300SRichard Henderson     } else {
395951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
396951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
397951c6300SRichard Henderson     }
398951c6300SRichard Henderson }
399951c6300SRichard Henderson 
400951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
401951c6300SRichard Henderson {
402951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
403951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
404951c6300SRichard Henderson     } else {
4055dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
406951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
407951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
408951c6300SRichard Henderson         tcg_temp_free_i32(t0);
409951c6300SRichard Henderson     }
410951c6300SRichard Henderson }
411951c6300SRichard Henderson 
4120e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4130e28d006SRichard Henderson {
4140e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4150e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
4160e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
4175dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
4185dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
4190e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4200e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4210e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4220e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4230e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4240e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4250e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4260e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4270e28d006SRichard Henderson     } else {
4280e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4290e28d006SRichard Henderson     }
4300e28d006SRichard Henderson }
4310e28d006SRichard Henderson 
4320e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4330e28d006SRichard Henderson {
43411d11d61SRichard Henderson     tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2));
4350e28d006SRichard Henderson }
4360e28d006SRichard Henderson 
4370e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4380e28d006SRichard Henderson {
4390e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4400e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4410e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4425dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
4435dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
4440e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4450e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4460e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4470e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4480e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4490e28d006SRichard Henderson         tcg_temp_free_i64(t2);
45014e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
45114e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
45214e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
45314e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
4545dd48602SRichard Henderson         TCGv_i32 z, t = tcg_temp_ebb_new_i32();
45514e99210SRichard Henderson 
45614e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
45714e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
45814e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
45914e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
46014e99210SRichard Henderson         } else {
46114e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
46214e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
46314e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
46414e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
46514e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
46614e99210SRichard Henderson         }
46711d11d61SRichard Henderson         z = tcg_constant_i32(0);
46814e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
46914e99210SRichard Henderson         tcg_temp_free_i32(t);
4700e28d006SRichard Henderson     } else {
4710e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4720e28d006SRichard Henderson     }
4730e28d006SRichard Henderson }
4740e28d006SRichard Henderson 
4750e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4760e28d006SRichard Henderson {
47714e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
47814e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
4795dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
48014e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
48114e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
48214e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
48314e99210SRichard Henderson         tcg_temp_free_i32(t);
48414e99210SRichard Henderson     } else {
48511d11d61SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2));
4860e28d006SRichard Henderson     }
48714e99210SRichard Henderson }
4880e28d006SRichard Henderson 
489086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
490086920c2SRichard Henderson {
491086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4925dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
493086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
494086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
495086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
496086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
497086920c2SRichard Henderson         tcg_temp_free_i32(t);
498086920c2SRichard Henderson     } else {
499086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
500086920c2SRichard Henderson     }
501086920c2SRichard Henderson }
502086920c2SRichard Henderson 
503a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
504a768e4e9SRichard Henderson {
505a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
506a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
507a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
5085dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
509a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
510a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
511a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
512a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
513a768e4e9SRichard Henderson     } else {
514a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
515a768e4e9SRichard Henderson     }
516a768e4e9SRichard Henderson }
517a768e4e9SRichard Henderson 
518951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
519951c6300SRichard Henderson {
520951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
521951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
522951c6300SRichard Henderson     } else {
523951c6300SRichard Henderson         TCGv_i32 t0, t1;
524951c6300SRichard Henderson 
5255dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
5265dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
527951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
528951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
529951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
530951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
531951c6300SRichard Henderson         tcg_temp_free_i32(t0);
532951c6300SRichard Henderson         tcg_temp_free_i32(t1);
533951c6300SRichard Henderson     }
534951c6300SRichard Henderson }
535951c6300SRichard Henderson 
53607dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
537951c6300SRichard Henderson {
53807dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
539951c6300SRichard Henderson     /* some cases can be optimized here */
540951c6300SRichard Henderson     if (arg2 == 0) {
541951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
542951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
54311d11d61SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2));
544951c6300SRichard Henderson     } else {
545951c6300SRichard Henderson         TCGv_i32 t0, t1;
5465dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
5475dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
548951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
549951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
550951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
551951c6300SRichard Henderson         tcg_temp_free_i32(t0);
552951c6300SRichard Henderson         tcg_temp_free_i32(t1);
553951c6300SRichard Henderson     }
554951c6300SRichard Henderson }
555951c6300SRichard Henderson 
556951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
557951c6300SRichard Henderson {
558951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
559951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
560951c6300SRichard Henderson     } else {
561951c6300SRichard Henderson         TCGv_i32 t0, t1;
562951c6300SRichard Henderson 
5635dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
5645dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
565951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
566951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
567951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
568951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
569951c6300SRichard Henderson         tcg_temp_free_i32(t0);
570951c6300SRichard Henderson         tcg_temp_free_i32(t1);
571951c6300SRichard Henderson     }
572951c6300SRichard Henderson }
573951c6300SRichard Henderson 
57407dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
575951c6300SRichard Henderson {
57607dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
577951c6300SRichard Henderson     /* some cases can be optimized here */
578951c6300SRichard Henderson     if (arg2 == 0) {
579951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
580951c6300SRichard Henderson     } else {
581951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
582951c6300SRichard Henderson     }
583951c6300SRichard Henderson }
584951c6300SRichard Henderson 
585951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
586951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
587951c6300SRichard Henderson {
588951c6300SRichard Henderson     uint32_t mask;
589951c6300SRichard Henderson     TCGv_i32 t1;
590951c6300SRichard Henderson 
591951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
5920d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
593951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
594951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
595951c6300SRichard Henderson 
5960d0d309dSRichard Henderson     if (len == 32) {
597951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
598951c6300SRichard Henderson         return;
599951c6300SRichard Henderson     }
600951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
601951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
602951c6300SRichard Henderson         return;
603951c6300SRichard Henderson     }
604951c6300SRichard Henderson 
6055dd48602SRichard Henderson     t1 = tcg_temp_ebb_new_i32();
606951c6300SRichard Henderson 
607b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i32) {
608b0a60567SRichard Henderson         if (ofs + len == 32) {
609b0a60567SRichard Henderson             tcg_gen_shli_i32(t1, arg1, len);
610b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, t1, arg2, len);
611b0a60567SRichard Henderson             goto done;
612b0a60567SRichard Henderson         }
613b0a60567SRichard Henderson         if (ofs == 0) {
614b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, arg1, arg2, len);
615b0a60567SRichard Henderson             tcg_gen_rotli_i32(ret, ret, len);
616b0a60567SRichard Henderson             goto done;
617b0a60567SRichard Henderson         }
618b0a60567SRichard Henderson     }
619b0a60567SRichard Henderson 
620b0a60567SRichard Henderson     mask = (1u << len) - 1;
621951c6300SRichard Henderson     if (ofs + len < 32) {
622951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
623951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
624951c6300SRichard Henderson     } else {
625951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
626951c6300SRichard Henderson     }
627951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
628951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
629b0a60567SRichard Henderson  done:
630951c6300SRichard Henderson     tcg_temp_free_i32(t1);
631951c6300SRichard Henderson }
632951c6300SRichard Henderson 
63307cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
63407cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
63507cc68d5SRichard Henderson {
63607cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
63707cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
63807cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
63907cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
64007cc68d5SRichard Henderson 
64107cc68d5SRichard Henderson     if (ofs + len == 32) {
64207cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
64307cc68d5SRichard Henderson     } else if (ofs == 0) {
64407cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
64507cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
64607cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
64711d11d61SRichard Henderson         TCGv_i32 zero = tcg_constant_i32(0);
64807cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
64907cc68d5SRichard Henderson     } else {
65007cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
65107cc68d5SRichard Henderson            which allows ARG to stay live.  */
65207cc68d5SRichard Henderson         switch (len) {
65307cc68d5SRichard Henderson         case 16:
65407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
65507cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
65607cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
65707cc68d5SRichard Henderson                 return;
65807cc68d5SRichard Henderson             }
65907cc68d5SRichard Henderson             break;
66007cc68d5SRichard Henderson         case 8:
66107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
66207cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
66307cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
66407cc68d5SRichard Henderson                 return;
66507cc68d5SRichard Henderson             }
66607cc68d5SRichard Henderson             break;
66707cc68d5SRichard Henderson         }
66807cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
66907cc68d5SRichard Henderson         switch (ofs + len) {
67007cc68d5SRichard Henderson         case 16:
67107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
67207cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
67307cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
67407cc68d5SRichard Henderson                 return;
67507cc68d5SRichard Henderson             }
67607cc68d5SRichard Henderson             break;
67707cc68d5SRichard Henderson         case 8:
67807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
67907cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
68007cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
68107cc68d5SRichard Henderson                 return;
68207cc68d5SRichard Henderson             }
68307cc68d5SRichard Henderson             break;
68407cc68d5SRichard Henderson         }
68507cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
68607cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
68707cc68d5SRichard Henderson     }
68807cc68d5SRichard Henderson }
68907cc68d5SRichard Henderson 
6907ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
6917ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
6927ec8bab3SRichard Henderson {
6937ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
6947ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
6957ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
6967ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
6977ec8bab3SRichard Henderson 
6987ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
6997ec8bab3SRichard Henderson     if (ofs + len == 32) {
7007ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
7017ec8bab3SRichard Henderson         return;
7027ec8bab3SRichard Henderson     }
7037ec8bab3SRichard Henderson     if (ofs == 0) {
7047ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
7057ec8bab3SRichard Henderson         return;
7067ec8bab3SRichard Henderson     }
7077ec8bab3SRichard Henderson 
7087ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
7097ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7107ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
7117ec8bab3SRichard Henderson         return;
7127ec8bab3SRichard Henderson     }
7137ec8bab3SRichard Henderson 
7147ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
7157ec8bab3SRichard Henderson     switch (ofs + len) {
7167ec8bab3SRichard Henderson     case 16:
7177ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7187ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7197ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7207ec8bab3SRichard Henderson             return;
7217ec8bab3SRichard Henderson         }
7227ec8bab3SRichard Henderson         break;
7237ec8bab3SRichard Henderson     case 8:
7247ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7257ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7267ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7277ec8bab3SRichard Henderson             return;
7287ec8bab3SRichard Henderson         }
7297ec8bab3SRichard Henderson         break;
7307ec8bab3SRichard Henderson     }
7317ec8bab3SRichard Henderson 
7327ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7337ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7347ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7357ec8bab3SRichard Henderson     switch (len) {
7367ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7377ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7387ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7397ec8bab3SRichard Henderson         break;
7407ec8bab3SRichard Henderson     default:
7417ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7427ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7437ec8bab3SRichard Henderson         break;
7447ec8bab3SRichard Henderson     }
7457ec8bab3SRichard Henderson }
7467ec8bab3SRichard Henderson 
7477ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7487ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7497ec8bab3SRichard Henderson {
7507ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7517ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7527ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7537ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7547ec8bab3SRichard Henderson 
7557ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7567ec8bab3SRichard Henderson     if (ofs + len == 32) {
7577ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7587ec8bab3SRichard Henderson         return;
7597ec8bab3SRichard Henderson     }
7607ec8bab3SRichard Henderson     if (ofs == 0) {
7617ec8bab3SRichard Henderson         switch (len) {
7627ec8bab3SRichard Henderson         case 16:
7637ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7647ec8bab3SRichard Henderson             return;
7657ec8bab3SRichard Henderson         case 8:
7667ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7677ec8bab3SRichard Henderson             return;
7687ec8bab3SRichard Henderson         }
7697ec8bab3SRichard Henderson     }
7707ec8bab3SRichard Henderson 
7717ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7727ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7737ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7747ec8bab3SRichard Henderson         return;
7757ec8bab3SRichard Henderson     }
7767ec8bab3SRichard Henderson 
7777ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7787ec8bab3SRichard Henderson     switch (ofs + len) {
7797ec8bab3SRichard Henderson     case 16:
7807ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7817ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7827ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7837ec8bab3SRichard Henderson             return;
7847ec8bab3SRichard Henderson         }
7857ec8bab3SRichard Henderson         break;
7867ec8bab3SRichard Henderson     case 8:
7877ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7887ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7897ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7907ec8bab3SRichard Henderson             return;
7917ec8bab3SRichard Henderson         }
7927ec8bab3SRichard Henderson         break;
7937ec8bab3SRichard Henderson     }
7947ec8bab3SRichard Henderson     switch (len) {
7957ec8bab3SRichard Henderson     case 16:
7967ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7977ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7987ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
7997ec8bab3SRichard Henderson             return;
8007ec8bab3SRichard Henderson         }
8017ec8bab3SRichard Henderson         break;
8027ec8bab3SRichard Henderson     case 8:
8037ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8047ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8057ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
8067ec8bab3SRichard Henderson             return;
8077ec8bab3SRichard Henderson         }
8087ec8bab3SRichard Henderson         break;
8097ec8bab3SRichard Henderson     }
8107ec8bab3SRichard Henderson 
8117ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
8127ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
8137ec8bab3SRichard Henderson }
8147ec8bab3SRichard Henderson 
8152089fcc9SDavid Hildenbrand /*
8162089fcc9SDavid Hildenbrand  * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
8172089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
8182089fcc9SDavid Hildenbrand  */
8192089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
8202089fcc9SDavid Hildenbrand                           unsigned int ofs)
8212089fcc9SDavid Hildenbrand {
8222089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 32);
8232089fcc9SDavid Hildenbrand     if (ofs == 0) {
8242089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, al);
8252089fcc9SDavid Hildenbrand     } else if (ofs == 32) {
8262089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, ah);
8272089fcc9SDavid Hildenbrand     } else if (al == ah) {
8282089fcc9SDavid Hildenbrand         tcg_gen_rotri_i32(ret, al, ofs);
829fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i32) {
830fce1296fSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
8312089fcc9SDavid Hildenbrand     } else {
8325dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
8332089fcc9SDavid Hildenbrand         tcg_gen_shri_i32(t0, al, ofs);
8342089fcc9SDavid Hildenbrand         tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs);
8352089fcc9SDavid Hildenbrand         tcg_temp_free_i32(t0);
8362089fcc9SDavid Hildenbrand     }
8372089fcc9SDavid Hildenbrand }
8382089fcc9SDavid Hildenbrand 
839951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
840951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
841951c6300SRichard Henderson {
84237ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
84337ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
84437ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
84537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
84637ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
847951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
848951c6300SRichard Henderson     } else {
8495dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
8505dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
851951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
852951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
853951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
854951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
855951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
856951c6300SRichard Henderson         tcg_temp_free_i32(t0);
857951c6300SRichard Henderson         tcg_temp_free_i32(t1);
858951c6300SRichard Henderson     }
859951c6300SRichard Henderson }
860951c6300SRichard Henderson 
861951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
862951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
863951c6300SRichard Henderson {
864951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
865951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
866951c6300SRichard Henderson     } else {
8675dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
8685dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
869951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
870951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
871951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
872951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
873951c6300SRichard Henderson         tcg_temp_free_i64(t0);
874951c6300SRichard Henderson         tcg_temp_free_i64(t1);
875951c6300SRichard Henderson     }
876951c6300SRichard Henderson }
877951c6300SRichard Henderson 
878951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
879951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
880951c6300SRichard Henderson {
881951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
882951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
883951c6300SRichard Henderson     } else {
8845dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
8855dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
886951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
887951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
888951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
889951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
890951c6300SRichard Henderson         tcg_temp_free_i64(t0);
891951c6300SRichard Henderson         tcg_temp_free_i64(t1);
892951c6300SRichard Henderson     }
893951c6300SRichard Henderson }
894951c6300SRichard Henderson 
895951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
896951c6300SRichard Henderson {
897951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
898951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
899951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
9005dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
901951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
902951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
903951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
904951c6300SRichard Henderson         tcg_temp_free_i32(t);
9059fd86b51SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
9065dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
9075dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
908951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
909951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
910951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
911951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
912951c6300SRichard Henderson         tcg_temp_free_i64(t0);
913951c6300SRichard Henderson         tcg_temp_free_i64(t1);
9149fd86b51SRichard Henderson     } else {
9159fd86b51SRichard Henderson         qemu_build_not_reached();
916951c6300SRichard Henderson     }
917951c6300SRichard Henderson }
918951c6300SRichard Henderson 
919951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
920951c6300SRichard Henderson {
921951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
922951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
923951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
9245dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
925951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
926951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
927951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
928951c6300SRichard Henderson         tcg_temp_free_i32(t);
929951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
9305dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
9315dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
9325dd48602SRichard Henderson         TCGv_i32 t2 = tcg_temp_ebb_new_i32();
9335dd48602SRichard Henderson         TCGv_i32 t3 = tcg_temp_ebb_new_i32();
934951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
935951c6300SRichard Henderson         /* Adjust for negative inputs.  */
936951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
937951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
938951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
939951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
940951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
941951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
942951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
943951c6300SRichard Henderson         tcg_temp_free_i32(t0);
944951c6300SRichard Henderson         tcg_temp_free_i32(t1);
945951c6300SRichard Henderson         tcg_temp_free_i32(t2);
946951c6300SRichard Henderson         tcg_temp_free_i32(t3);
947951c6300SRichard Henderson     } else {
9485dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
9495dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
950951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
951951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
952951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
953951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
954951c6300SRichard Henderson         tcg_temp_free_i64(t0);
955951c6300SRichard Henderson         tcg_temp_free_i64(t1);
956951c6300SRichard Henderson     }
957951c6300SRichard Henderson }
958951c6300SRichard Henderson 
9595087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9605087abfbSRichard Henderson {
9615087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9625dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
9635dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
9645dd48602SRichard Henderson         TCGv_i32 t2 = tcg_temp_ebb_new_i32();
9655087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9665087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9675087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9685087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9695087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9705087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9715087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9725087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9735087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9745087abfbSRichard Henderson     } else {
9755dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
9765dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
9775087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9785087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9795087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9805087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9815087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9825087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9835087abfbSRichard Henderson     }
9845087abfbSRichard Henderson }
9855087abfbSRichard Henderson 
986951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
987951c6300SRichard Henderson {
988951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
989951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
990951c6300SRichard Henderson     } else {
991951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
992951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
993951c6300SRichard Henderson     }
994951c6300SRichard Henderson }
995951c6300SRichard Henderson 
996951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
997951c6300SRichard Henderson {
998951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
999951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
1000951c6300SRichard Henderson     } else {
1001951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
1002951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
1003951c6300SRichard Henderson     }
1004951c6300SRichard Henderson }
1005951c6300SRichard Henderson 
1006951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
1007951c6300SRichard Henderson {
1008951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
1009951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
1010951c6300SRichard Henderson     } else {
1011951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
1012951c6300SRichard Henderson     }
1013951c6300SRichard Henderson }
1014951c6300SRichard Henderson 
1015951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
1016951c6300SRichard Henderson {
1017951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
1018951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
1019951c6300SRichard Henderson     } else {
1020951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1021951c6300SRichard Henderson     }
1022951c6300SRichard Henderson }
1023951c6300SRichard Henderson 
10242b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
1025951c6300SRichard Henderson {
10262b836c2aSRichard Henderson     /* Only one extension flag may be present. */
10272b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
10282b836c2aSRichard Henderson 
1029951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
10302b836c2aSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags);
1031951c6300SRichard Henderson     } else {
10325dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
10335dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
1034951c6300SRichard Henderson 
10352b836c2aSRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);
10362b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
10372b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t0, t0);
10382b836c2aSRichard Henderson         }
10392b836c2aSRichard Henderson 
10402b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
10412b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 24);
10422b836c2aSRichard Henderson             tcg_gen_sari_i32(t1, t1, 16);
10432b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
10442b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t1, arg);
10452b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, t1, 8);
10462b836c2aSRichard Henderson         } else {
10472b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 8);
10482b836c2aSRichard Henderson         }
10492b836c2aSRichard Henderson 
10502b836c2aSRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1051951c6300SRichard Henderson         tcg_temp_free_i32(t0);
10522b836c2aSRichard Henderson         tcg_temp_free_i32(t1);
1053951c6300SRichard Henderson     }
1054951c6300SRichard Henderson }
1055951c6300SRichard Henderson 
1056951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1057951c6300SRichard Henderson {
1058951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1059587195bdSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
1060951c6300SRichard Henderson     } else {
10615dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
10625dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
106311d11d61SRichard Henderson         TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
1064951c6300SRichard Henderson 
1065a686dc71SRichard Henderson                                         /* arg = abcd */
1066a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);   /*  t0 = .abc */
1067a686dc71SRichard Henderson         tcg_gen_and_i32(t1, arg, t2);   /*  t1 = .b.d */
1068a686dc71SRichard Henderson         tcg_gen_and_i32(t0, t0, t2);    /*  t0 = .a.c */
1069a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = b.d. */
1070a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = badc */
1071951c6300SRichard Henderson 
1072a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, ret, 16);  /*  t0 = ..ba */
1073a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, ret, 16);  /*  t1 = dc.. */
1074a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = dcba */
1075951c6300SRichard Henderson 
1076951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1077951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1078951c6300SRichard Henderson     }
1079951c6300SRichard Henderson }
1080951c6300SRichard Henderson 
108146be8425SRichard Henderson void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg)
108246be8425SRichard Henderson {
108346be8425SRichard Henderson     /* Swapping 2 16-bit elements is a rotate. */
108446be8425SRichard Henderson     tcg_gen_rotli_i32(ret, arg, 16);
108546be8425SRichard Henderson }
108646be8425SRichard Henderson 
1087b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1088b87fb8cdSRichard Henderson {
1089b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1090b87fb8cdSRichard Henderson }
1091b87fb8cdSRichard Henderson 
1092b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1093b87fb8cdSRichard Henderson {
1094b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1095b87fb8cdSRichard Henderson }
1096b87fb8cdSRichard Henderson 
1097b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1098b87fb8cdSRichard Henderson {
1099b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1100b87fb8cdSRichard Henderson }
1101b87fb8cdSRichard Henderson 
1102b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1103b87fb8cdSRichard Henderson {
1104b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1105b87fb8cdSRichard Henderson }
1106b87fb8cdSRichard Henderson 
1107ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
1108ff1f11f7SRichard Henderson {
11095dd48602SRichard Henderson     TCGv_i32 t = tcg_temp_ebb_new_i32();
1110ff1f11f7SRichard Henderson 
1111ff1f11f7SRichard Henderson     tcg_gen_sari_i32(t, a, 31);
1112ff1f11f7SRichard Henderson     tcg_gen_xor_i32(ret, a, t);
1113ff1f11f7SRichard Henderson     tcg_gen_sub_i32(ret, ret, t);
1114ff1f11f7SRichard Henderson     tcg_temp_free_i32(t);
1115ff1f11f7SRichard Henderson }
1116ff1f11f7SRichard Henderson 
1117951c6300SRichard Henderson /* 64-bit ops */
1118951c6300SRichard Henderson 
1119951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1120951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1121951c6300SRichard Henderson 
1122951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1123951c6300SRichard Henderson {
1124951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1125951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1126951c6300SRichard Henderson }
1127951c6300SRichard Henderson 
1128951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1129951c6300SRichard Henderson {
113011d11d61SRichard Henderson     TCGTemp *ts = tcgv_i64_temp(arg);
113111d11d61SRichard Henderson 
113211d11d61SRichard Henderson     /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
113311d11d61SRichard Henderson     if (ts->kind == TEMP_CONST) {
113411d11d61SRichard Henderson         tcg_gen_movi_i64(ret, ts->val);
113511d11d61SRichard Henderson     } else {
1136951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1137951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1138951c6300SRichard Henderson     }
113911d11d61SRichard Henderson }
1140951c6300SRichard Henderson 
1141951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1142951c6300SRichard Henderson {
1143951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1144951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1145951c6300SRichard Henderson }
1146951c6300SRichard Henderson 
1147951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1148951c6300SRichard Henderson {
1149951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1150951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1151951c6300SRichard Henderson }
1152951c6300SRichard Henderson 
1153951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1154951c6300SRichard Henderson {
1155951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11563ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1157951c6300SRichard Henderson }
1158951c6300SRichard Henderson 
1159951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1160951c6300SRichard Henderson {
1161951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1162951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1163951c6300SRichard Henderson }
1164951c6300SRichard Henderson 
1165951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1166951c6300SRichard Henderson {
1167951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1168951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1169951c6300SRichard Henderson }
1170951c6300SRichard Henderson 
1171951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1172951c6300SRichard Henderson {
1173951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1174951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1175951c6300SRichard Henderson }
1176951c6300SRichard Henderson 
1177951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1178951c6300SRichard Henderson {
1179951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1180951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1181951c6300SRichard Henderson }
1182951c6300SRichard Henderson 
1183951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1184951c6300SRichard Henderson {
1185951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1186951c6300SRichard Henderson        they cannot be the same temporary */
1187e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1188951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1189951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1190951c6300SRichard Henderson #else
1191951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1192951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1193951c6300SRichard Henderson #endif
1194951c6300SRichard Henderson }
1195951c6300SRichard Henderson 
1196d56fea79SRichard Henderson void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1197d56fea79SRichard Henderson {
1198d56fea79SRichard Henderson     tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset);
1199d56fea79SRichard Henderson }
1200d56fea79SRichard Henderson 
1201d56fea79SRichard Henderson void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1202d56fea79SRichard Henderson {
1203d56fea79SRichard Henderson     tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset);
1204d56fea79SRichard Henderson }
1205d56fea79SRichard Henderson 
1206d56fea79SRichard Henderson void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1207d56fea79SRichard Henderson {
1208d56fea79SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1209d56fea79SRichard Henderson }
1210d56fea79SRichard Henderson 
1211951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1212951c6300SRichard Henderson {
1213e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1214951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1215951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1216951c6300SRichard Henderson #else
1217951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1218951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1219951c6300SRichard Henderson #endif
1220951c6300SRichard Henderson }
1221951c6300SRichard Henderson 
1222d56fea79SRichard Henderson void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1223d56fea79SRichard Henderson {
1224d56fea79SRichard Henderson     tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1),
1225d56fea79SRichard Henderson                      TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2));
1226d56fea79SRichard Henderson }
1227d56fea79SRichard Henderson 
1228d56fea79SRichard Henderson void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1229d56fea79SRichard Henderson {
1230d56fea79SRichard Henderson     tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1),
1231d56fea79SRichard Henderson                      TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2));
1232d56fea79SRichard Henderson }
1233d56fea79SRichard Henderson 
1234951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1235951c6300SRichard Henderson {
1236951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1237951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1238951c6300SRichard Henderson }
1239951c6300SRichard Henderson 
1240951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1241951c6300SRichard Henderson {
1242951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1243951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1244951c6300SRichard Henderson }
1245951c6300SRichard Henderson 
1246951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1247951c6300SRichard Henderson {
1248951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1249951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1250951c6300SRichard Henderson }
1251951c6300SRichard Henderson 
1252951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1253951c6300SRichard Henderson {
1254951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1255951c6300SRichard Henderson }
1256951c6300SRichard Henderson 
1257951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1258951c6300SRichard Henderson {
1259951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1260951c6300SRichard Henderson }
1261951c6300SRichard Henderson 
1262951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1263951c6300SRichard Henderson {
1264951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1265951c6300SRichard Henderson }
1266951c6300SRichard Henderson 
1267951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1268951c6300SRichard Henderson {
1269951c6300SRichard Henderson     TCGv_i64 t0;
1270951c6300SRichard Henderson     TCGv_i32 t1;
1271951c6300SRichard Henderson 
12725dd48602SRichard Henderson     t0 = tcg_temp_ebb_new_i64();
12735dd48602SRichard Henderson     t1 = tcg_temp_ebb_new_i32();
1274951c6300SRichard Henderson 
1275951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1276951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1277951c6300SRichard Henderson 
1278951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1279951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1280951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1281951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1282951c6300SRichard Henderson 
1283951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1284951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1285951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1286951c6300SRichard Henderson }
128711d11d61SRichard Henderson 
128811d11d61SRichard Henderson #else
128911d11d61SRichard Henderson 
129011d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
129111d11d61SRichard Henderson {
129211d11d61SRichard Henderson     tcg_gen_mov_i64(ret, tcg_constant_i64(arg));
129311d11d61SRichard Henderson }
129411d11d61SRichard Henderson 
1295951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1296951c6300SRichard Henderson 
1297951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1298951c6300SRichard Henderson {
1299951c6300SRichard Henderson     /* some cases can be optimized here */
1300951c6300SRichard Henderson     if (arg2 == 0) {
1301951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
130211d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
130311d11d61SRichard Henderson         tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2));
1304951c6300SRichard Henderson     } else {
130511d11d61SRichard Henderson         tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
130611d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
130711d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1308951c6300SRichard Henderson     }
1309951c6300SRichard Henderson }
1310951c6300SRichard Henderson 
1311951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1312951c6300SRichard Henderson {
1313951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1314951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1315951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
131611d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
131711d11d61SRichard Henderson         tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
1318951c6300SRichard Henderson     } else {
131911d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
132011d11d61SRichard Henderson                          tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32),
132111d11d61SRichard Henderson                          TCGV_LOW(arg2), TCGV_HIGH(arg2));
1322951c6300SRichard Henderson     }
1323951c6300SRichard Henderson }
1324951c6300SRichard Henderson 
1325951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1326951c6300SRichard Henderson {
1327951c6300SRichard Henderson     /* some cases can be optimized here */
1328951c6300SRichard Henderson     if (arg2 == 0) {
1329951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
133011d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
133111d11d61SRichard Henderson         tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2));
1332951c6300SRichard Henderson     } else {
133311d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
133411d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
133511d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1336951c6300SRichard Henderson     }
1337951c6300SRichard Henderson }
1338951c6300SRichard Henderson 
1339474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1340951c6300SRichard Henderson {
13413a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1342951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1343951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13443a13c3f3SRichard Henderson         return;
13453a13c3f3SRichard Henderson     }
13463a13c3f3SRichard Henderson 
1347951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1348951c6300SRichard Henderson     switch (arg2) {
1349951c6300SRichard Henderson     case 0:
1350951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1351951c6300SRichard Henderson         return;
1352474b2e8fSRichard Henderson     case -1:
1353951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1354951c6300SRichard Henderson         return;
1355474b2e8fSRichard Henderson     case 0xff:
1356951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1357951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1358951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1359951c6300SRichard Henderson             return;
1360951c6300SRichard Henderson         }
1361951c6300SRichard Henderson         break;
1362474b2e8fSRichard Henderson     case 0xffff:
1363951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1364951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1365951c6300SRichard Henderson             return;
1366951c6300SRichard Henderson         }
1367951c6300SRichard Henderson         break;
1368474b2e8fSRichard Henderson     case 0xffffffffu:
1369951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1370951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1371951c6300SRichard Henderson             return;
1372951c6300SRichard Henderson         }
1373951c6300SRichard Henderson         break;
1374951c6300SRichard Henderson     }
137511d11d61SRichard Henderson 
137611d11d61SRichard Henderson     tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2));
1377951c6300SRichard Henderson }
1378951c6300SRichard Henderson 
1379951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1380951c6300SRichard Henderson {
13813a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1382951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1383951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13843a13c3f3SRichard Henderson         return;
13853a13c3f3SRichard Henderson     }
1386951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1387951c6300SRichard Henderson     if (arg2 == -1) {
1388951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1389951c6300SRichard Henderson     } else if (arg2 == 0) {
1390951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1391951c6300SRichard Henderson     } else {
139211d11d61SRichard Henderson         tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2));
1393951c6300SRichard Henderson     }
1394951c6300SRichard Henderson }
1395951c6300SRichard Henderson 
1396951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1397951c6300SRichard Henderson {
13983a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1399951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1400951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
14013a13c3f3SRichard Henderson         return;
14023a13c3f3SRichard Henderson     }
1403951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1404951c6300SRichard Henderson     if (arg2 == 0) {
1405951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1406951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1407951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1408951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1409951c6300SRichard Henderson     } else {
141011d11d61SRichard Henderson         tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2));
1411951c6300SRichard Henderson     }
1412951c6300SRichard Henderson }
1413951c6300SRichard Henderson 
1414951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1415951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1416951c6300SRichard Henderson {
1417951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1418951c6300SRichard Henderson     if (c == 0) {
1419951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1420951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1421951c6300SRichard Henderson     } else if (c >= 32) {
1422951c6300SRichard Henderson         c -= 32;
1423951c6300SRichard Henderson         if (right) {
1424951c6300SRichard Henderson             if (arith) {
1425951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1426951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1427951c6300SRichard Henderson             } else {
1428951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1429951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1430951c6300SRichard Henderson             }
1431951c6300SRichard Henderson         } else {
1432951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1433951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1434951c6300SRichard Henderson         }
143502616badSRichard Henderson     } else if (right) {
143602616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
143702616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_LOW(ret),
143802616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1439951c6300SRichard Henderson         } else {
1440951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
144102616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret),
144202616badSRichard Henderson                                 TCGV_HIGH(arg1), 32 - c, c);
1443951c6300SRichard Henderson         }
144402616badSRichard Henderson         if (arith) {
144502616badSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
144602616badSRichard Henderson         } else {
144702616badSRichard Henderson             tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
144802616badSRichard Henderson         }
144902616badSRichard Henderson     } else {
145002616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
145102616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_HIGH(ret),
145202616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
145302616badSRichard Henderson         } else {
14545dd48602SRichard Henderson             TCGv_i32 t0 = tcg_temp_ebb_new_i32();
145502616badSRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
145602616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), t0,
145702616badSRichard Henderson                                 TCGV_HIGH(arg1), c, 32 - c);
1458951c6300SRichard Henderson             tcg_temp_free_i32(t0);
145902616badSRichard Henderson         }
146002616badSRichard Henderson         tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1461951c6300SRichard Henderson     }
1462951c6300SRichard Henderson }
1463951c6300SRichard Henderson 
1464474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1465951c6300SRichard Henderson {
1466474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14673a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14683a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
14693a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1470951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1471951c6300SRichard Henderson     } else {
147211d11d61SRichard Henderson         tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2));
1473951c6300SRichard Henderson     }
1474951c6300SRichard Henderson }
1475951c6300SRichard Henderson 
1476474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1477951c6300SRichard Henderson {
1478474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14793a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14803a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
14813a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1482951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1483951c6300SRichard Henderson     } else {
148411d11d61SRichard Henderson         tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2));
1485951c6300SRichard Henderson     }
1486951c6300SRichard Henderson }
1487951c6300SRichard Henderson 
1488474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1489951c6300SRichard Henderson {
1490474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14913a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14923a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
14933a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1494951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1495951c6300SRichard Henderson     } else {
149611d11d61SRichard Henderson         tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2));
1497951c6300SRichard Henderson     }
1498951c6300SRichard Henderson }
1499951c6300SRichard Henderson 
150042a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1501951c6300SRichard Henderson {
1502951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
150342a268c2SRichard Henderson         tcg_gen_br(l);
1504951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
15053a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1506951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1507951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
150842a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
15093a13c3f3SRichard Henderson         } else {
151042a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
151142a268c2SRichard Henderson                               label_arg(l));
15123a13c3f3SRichard Henderson         }
1513f85b1fc4SRichard Henderson         add_last_as_label_use(l);
1514951c6300SRichard Henderson     }
1515951c6300SRichard Henderson }
1516951c6300SRichard Henderson 
151742a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1518951c6300SRichard Henderson {
151911d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
152011d11d61SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l);
152111d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
152242a268c2SRichard Henderson         tcg_gen_br(l);
1523951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
152411d11d61SRichard Henderson         tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
152511d11d61SRichard Henderson                           TCGV_LOW(arg1), TCGV_HIGH(arg1),
152611d11d61SRichard Henderson                           tcg_constant_i32(arg2),
152711d11d61SRichard Henderson                           tcg_constant_i32(arg2 >> 32),
152811d11d61SRichard Henderson                           cond, label_arg(l));
1529f85b1fc4SRichard Henderson         add_last_as_label_use(l);
1530951c6300SRichard Henderson     }
1531951c6300SRichard Henderson }
1532951c6300SRichard Henderson 
1533951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1534951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1535951c6300SRichard Henderson {
1536951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1537951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1538951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1539951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1540951c6300SRichard Henderson     } else {
15413a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1542951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1543951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1544951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1545951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15463a13c3f3SRichard Henderson         } else {
1547951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
15483a13c3f3SRichard Henderson         }
1549951c6300SRichard Henderson     }
1550951c6300SRichard Henderson }
1551951c6300SRichard Henderson 
1552951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1553951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1554951c6300SRichard Henderson {
155511d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
155611d11d61SRichard Henderson         tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2));
155711d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
155811d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 1);
155911d11d61SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
156011d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 0);
156111d11d61SRichard Henderson     } else {
156211d11d61SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
156311d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
156411d11d61SRichard Henderson                          tcg_constant_i32(arg2),
156511d11d61SRichard Henderson                          tcg_constant_i32(arg2 >> 32), cond);
156611d11d61SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
156711d11d61SRichard Henderson     }
1568951c6300SRichard Henderson }
1569951c6300SRichard Henderson 
1570951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1571951c6300SRichard Henderson {
1572b2e3ae94SRichard Henderson     if (arg2 == 0) {
1573b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1574b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1575b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1576b2e3ae94SRichard Henderson     } else {
1577f04de891SRichard Henderson         tcg_gen_mul_i64(ret, arg1, tcg_constant_i64(arg2));
1578951c6300SRichard Henderson     }
1579b2e3ae94SRichard Henderson }
1580951c6300SRichard Henderson 
1581951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1582951c6300SRichard Henderson {
1583951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1584951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1585951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
15865dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1587951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1588951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1589951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1590951c6300SRichard Henderson     } else {
1591951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1592951c6300SRichard Henderson     }
1593951c6300SRichard Henderson }
1594951c6300SRichard Henderson 
1595951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1596951c6300SRichard Henderson {
1597951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1598951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1599951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
16005dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1601951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1602951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1603951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1604951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1605951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16065dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1607951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1608951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1609951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1610951c6300SRichard Henderson     } else {
1611951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1612951c6300SRichard Henderson     }
1613951c6300SRichard Henderson }
1614951c6300SRichard Henderson 
1615951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1616951c6300SRichard Henderson {
1617951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1618951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1619951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16205dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1621951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1622951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1623951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1624951c6300SRichard Henderson     } else {
1625951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1626951c6300SRichard Henderson     }
1627951c6300SRichard Henderson }
1628951c6300SRichard Henderson 
1629951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1630951c6300SRichard Henderson {
1631951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1632951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1633951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
16345dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1635951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1636951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1637951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1638951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1639951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
16405dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1641951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1642951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1643951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1644951c6300SRichard Henderson     } else {
1645951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1646951c6300SRichard Henderson     }
1647951c6300SRichard Henderson }
1648951c6300SRichard Henderson 
1649951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1650951c6300SRichard Henderson {
16513a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1652951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1653951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1655951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1656951c6300SRichard Henderson     } else {
1657951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1658951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1659951c6300SRichard Henderson     }
1660951c6300SRichard Henderson }
1661951c6300SRichard Henderson 
1662951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1663951c6300SRichard Henderson {
16643a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1665951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1666951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16673a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1668951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1669951c6300SRichard Henderson     } else {
1670951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1671951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1672951c6300SRichard Henderson     }
1673951c6300SRichard Henderson }
1674951c6300SRichard Henderson 
1675951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1676951c6300SRichard Henderson {
16773a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1678951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1679951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16803a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1681951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1682951c6300SRichard Henderson     } else {
1683951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1684951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1685951c6300SRichard Henderson     }
1686951c6300SRichard Henderson }
1687951c6300SRichard Henderson 
1688951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1689951c6300SRichard Henderson {
16903a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1691951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1692951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16933a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1694951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1695951c6300SRichard Henderson     } else {
1696951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1697951c6300SRichard Henderson     }
1698951c6300SRichard Henderson }
1699951c6300SRichard Henderson 
1700951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1701951c6300SRichard Henderson {
17023a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1703951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1704951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17053a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1706951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1707951c6300SRichard Henderson     } else {
1708951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1709951c6300SRichard Henderson     }
1710951c6300SRichard Henderson }
1711951c6300SRichard Henderson 
1712951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1713951c6300SRichard Henderson {
17143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1715951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1716951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17173a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1718951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1719951c6300SRichard Henderson     } else {
1720951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1721951c6300SRichard Henderson     }
1722951c6300SRichard Henderson }
1723951c6300SRichard Henderson 
17242b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1725951c6300SRichard Henderson {
17262b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17272b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17282b836c2aSRichard Henderson 
17293a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17302b836c2aSRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags);
17312b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17322b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17332b836c2aSRichard Henderson         } else {
1734951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17352b836c2aSRichard Henderson         }
17363a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
17372b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags);
1738951c6300SRichard Henderson     } else {
17395dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
17405dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
1741951c6300SRichard Henderson 
17422b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);
17432b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
17442b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t0, t0);
17452b836c2aSRichard Henderson         }
17462b836c2aSRichard Henderson 
17472b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17482b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 56);
17492b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 48);
17502b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
17512b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t1, arg);
17522b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, t1, 8);
17532b836c2aSRichard Henderson         } else {
17542b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 8);
17552b836c2aSRichard Henderson         }
17562b836c2aSRichard Henderson 
17572b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1758951c6300SRichard Henderson         tcg_temp_free_i64(t0);
17592b836c2aSRichard Henderson         tcg_temp_free_i64(t1);
1760951c6300SRichard Henderson     }
1761951c6300SRichard Henderson }
1762951c6300SRichard Henderson 
17632b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1764951c6300SRichard Henderson {
17652b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17662b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17672b836c2aSRichard Henderson 
17683a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1769951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17702b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17712b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17722b836c2aSRichard Henderson         } else {
1773951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17742b836c2aSRichard Henderson         }
17753a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
17762b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags);
1777951c6300SRichard Henderson     } else {
17785dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
17795dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
178011d11d61SRichard Henderson         TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
1781951c6300SRichard Henderson 
17822b836c2aSRichard Henderson                                             /* arg = xxxxabcd */
17832b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);       /*  t0 = .xxxxabc */
1784a686dc71SRichard Henderson         tcg_gen_and_i64(t1, arg, t2);       /*  t1 = .....b.d */
1785a686dc71SRichard Henderson         tcg_gen_and_i64(t0, t0, t2);        /*  t0 = .....a.c */
1786a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);        /*  t1 = ....b.d. */
1787a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ....badc */
1788951c6300SRichard Henderson 
1789a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, ret, 48);      /*  t1 = dc...... */
1790a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);      /*  t0 = ......ba */
17912b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17922b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 32);   /*  t1 = ssssdc.. */
17932b836c2aSRichard Henderson         } else {
1794a686dc71SRichard Henderson             tcg_gen_shri_i64(t1, t1, 32);   /*  t1 = ....dc.. */
17952b836c2aSRichard Henderson         }
17962b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ssssdcba */
1797951c6300SRichard Henderson 
1798951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1799951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1800951c6300SRichard Henderson     }
1801951c6300SRichard Henderson }
1802951c6300SRichard Henderson 
1803951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1804951c6300SRichard Henderson {
18053a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1806951c6300SRichard Henderson         TCGv_i32 t0, t1;
18075dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i32();
18085dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i32();
1809951c6300SRichard Henderson 
1810951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1811951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1812951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1813951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1814951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1815951c6300SRichard Henderson         tcg_temp_free_i32(t1);
18163a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1817587195bdSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
1818951c6300SRichard Henderson     } else {
18195dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
18205dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
18215dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
1822951c6300SRichard Henderson 
18239e821eabSRichard Henderson                                         /* arg = abcdefgh */
18249e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
18259e821eabSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .abcdefg */
18269e821eabSRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .b.d.f.h */
18279e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .a.c.e.g */
18289e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = b.d.f.h. */
18299e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = badcfehg */
1830951c6300SRichard Henderson 
18319e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
18329e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ..badcfe */
18339e821eabSRichard Henderson         tcg_gen_and_i64(t1, ret, t2);   /*  t1 = ..dc..hg */
18349e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = ..ba..fe */
18359e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 16);   /*  t1 = dc..hg.. */
18369e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = dcbahgfe */
1837951c6300SRichard Henderson 
18389e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 32);  /*  t0 = ....dcba */
18399e821eabSRichard Henderson         tcg_gen_shli_i64(t1, ret, 32);  /*  t1 = hgfe.... */
18409e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = hgfedcba */
1841951c6300SRichard Henderson 
1842951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1843951c6300SRichard Henderson         tcg_temp_free_i64(t1);
18449e821eabSRichard Henderson         tcg_temp_free_i64(t2);
1845951c6300SRichard Henderson     }
1846951c6300SRichard Henderson }
1847951c6300SRichard Henderson 
184846be8425SRichard Henderson void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg)
184946be8425SRichard Henderson {
185046be8425SRichard Henderson     uint64_t m = 0x0000ffff0000ffffull;
18515dd48602SRichard Henderson     TCGv_i64 t0 = tcg_temp_ebb_new_i64();
18525dd48602SRichard Henderson     TCGv_i64 t1 = tcg_temp_ebb_new_i64();
185346be8425SRichard Henderson 
185446be8425SRichard Henderson     /* See include/qemu/bitops.h, hswap64. */
185546be8425SRichard Henderson     tcg_gen_rotli_i64(t1, arg, 32);
185646be8425SRichard Henderson     tcg_gen_andi_i64(t0, t1, m);
185746be8425SRichard Henderson     tcg_gen_shli_i64(t0, t0, 16);
185846be8425SRichard Henderson     tcg_gen_shri_i64(t1, t1, 16);
185946be8425SRichard Henderson     tcg_gen_andi_i64(t1, t1, m);
186046be8425SRichard Henderson     tcg_gen_or_i64(ret, t0, t1);
186146be8425SRichard Henderson 
186246be8425SRichard Henderson     tcg_temp_free_i64(t0);
186346be8425SRichard Henderson     tcg_temp_free_i64(t1);
186446be8425SRichard Henderson }
186546be8425SRichard Henderson 
186646be8425SRichard Henderson void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg)
186746be8425SRichard Henderson {
186846be8425SRichard Henderson     /* Swapping 2 32-bit elements is a rotate. */
186946be8425SRichard Henderson     tcg_gen_rotli_i64(ret, arg, 32);
187046be8425SRichard Henderson }
187146be8425SRichard Henderson 
1872951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1873951c6300SRichard Henderson {
18743a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18753a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
18763a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
18773a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1878951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1879951c6300SRichard Henderson     } else {
1880951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1881951c6300SRichard Henderson     }
1882951c6300SRichard Henderson }
1883951c6300SRichard Henderson 
1884951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1885951c6300SRichard Henderson {
18863a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18873a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18883a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18893a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1890951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1891951c6300SRichard Henderson     } else {
18925dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1893951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1894951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1895951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1896951c6300SRichard Henderson     }
1897951c6300SRichard Henderson }
1898951c6300SRichard Henderson 
1899951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1900951c6300SRichard Henderson {
19013a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19023a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19033a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19043a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1905951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1906951c6300SRichard Henderson     } else {
1907951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1908951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1909951c6300SRichard Henderson     }
1910951c6300SRichard Henderson }
1911951c6300SRichard Henderson 
1912951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1913951c6300SRichard Henderson {
19143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19153a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19163a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19173a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1918951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1919951c6300SRichard Henderson     } else {
1920951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1921951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1922951c6300SRichard Henderson     }
1923951c6300SRichard Henderson }
1924951c6300SRichard Henderson 
1925951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1926951c6300SRichard Henderson {
19273a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19283a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19293a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19303a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1931951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1932951c6300SRichard Henderson     } else {
1933951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1934951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1935951c6300SRichard Henderson     }
1936951c6300SRichard Henderson }
1937951c6300SRichard Henderson 
1938951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1939951c6300SRichard Henderson {
19403a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19413a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19423a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19433a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1944951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1945951c6300SRichard Henderson     } else {
19465dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1947951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1948951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1949951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1950951c6300SRichard Henderson     }
1951951c6300SRichard Henderson }
1952951c6300SRichard Henderson 
19530e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
19540e28d006SRichard Henderson {
19550e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
19560e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
19570e28d006SRichard Henderson     } else {
19580e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
19590e28d006SRichard Henderson     }
19600e28d006SRichard Henderson }
19610e28d006SRichard Henderson 
19620e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
19630e28d006SRichard Henderson {
19640e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
19650e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
19660e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
19675dd48602SRichard Henderson         TCGv_i32 t = tcg_temp_ebb_new_i32();
196811d11d61SRichard Henderson         tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32);
19690e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
19700e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
19710e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
19720e28d006SRichard Henderson         tcg_temp_free_i32(t);
19730e28d006SRichard Henderson     } else {
1974f04de891SRichard Henderson         tcg_gen_clz_i64(ret, arg1, tcg_constant_i64(arg2));
19750e28d006SRichard Henderson     }
19760e28d006SRichard Henderson }
19770e28d006SRichard Henderson 
19780e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
19790e28d006SRichard Henderson {
19800e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
19810e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
198214e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
19835dd48602SRichard Henderson         TCGv_i64 z, t = tcg_temp_ebb_new_i64();
198414e99210SRichard Henderson 
198514e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
198614e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
198714e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
198814e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
198914e99210SRichard Henderson         } else {
199014e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
199114e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
199214e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
199314e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
199414e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
199514e99210SRichard Henderson         }
199611d11d61SRichard Henderson         z = tcg_constant_i64(0);
199714e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
199814e99210SRichard Henderson         tcg_temp_free_i64(t);
199914e99210SRichard Henderson         tcg_temp_free_i64(z);
20000e28d006SRichard Henderson     } else {
20010e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
20020e28d006SRichard Henderson     }
20030e28d006SRichard Henderson }
20040e28d006SRichard Henderson 
20050e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
20060e28d006SRichard Henderson {
20070e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
20080e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
20090e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
20105dd48602SRichard Henderson         TCGv_i32 t32 = tcg_temp_ebb_new_i32();
201111d11d61SRichard Henderson         tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32);
20120e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
20130e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
20140e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
20150e28d006SRichard Henderson         tcg_temp_free_i32(t32);
201614e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
201714e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
201814e99210SRichard Henderson                && arg2 == 64) {
201914e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
20205dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
202114e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
202214e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
202314e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
202414e99210SRichard Henderson         tcg_temp_free_i64(t);
20250e28d006SRichard Henderson     } else {
2026f04de891SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, tcg_constant_i64(arg2));
20270e28d006SRichard Henderson     }
20280e28d006SRichard Henderson }
20290e28d006SRichard Henderson 
2030086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
2031086920c2SRichard Henderson {
2032086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
20335dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2034086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
2035086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
2036086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
2037086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
2038086920c2SRichard Henderson         tcg_temp_free_i64(t);
2039086920c2SRichard Henderson     } else {
2040086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
2041086920c2SRichard Henderson     }
2042086920c2SRichard Henderson }
2043086920c2SRichard Henderson 
2044a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
2045a768e4e9SRichard Henderson {
2046a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
2047a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
2048a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
2049a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2050a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2051a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
2052a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
2053a768e4e9SRichard Henderson     } else {
2054a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
2055a768e4e9SRichard Henderson     }
2056a768e4e9SRichard Henderson }
2057a768e4e9SRichard Henderson 
2058951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2059951c6300SRichard Henderson {
2060951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2061951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
2062951c6300SRichard Henderson     } else {
2063951c6300SRichard Henderson         TCGv_i64 t0, t1;
20645dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i64();
20655dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i64();
2066951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
2067951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2068951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
2069951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2070951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2071951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2072951c6300SRichard Henderson     }
2073951c6300SRichard Henderson }
2074951c6300SRichard Henderson 
207507dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2076951c6300SRichard Henderson {
207707dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2078951c6300SRichard Henderson     /* some cases can be optimized here */
2079951c6300SRichard Henderson     if (arg2 == 0) {
2080951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2081951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
208211d11d61SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2));
2083951c6300SRichard Henderson     } else {
2084951c6300SRichard Henderson         TCGv_i64 t0, t1;
20855dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i64();
20865dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i64();
2087951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
2088951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
2089951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2090951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2091951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2092951c6300SRichard Henderson     }
2093951c6300SRichard Henderson }
2094951c6300SRichard Henderson 
2095951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2096951c6300SRichard Henderson {
2097951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2098951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
2099951c6300SRichard Henderson     } else {
2100951c6300SRichard Henderson         TCGv_i64 t0, t1;
21015dd48602SRichard Henderson         t0 = tcg_temp_ebb_new_i64();
21025dd48602SRichard Henderson         t1 = tcg_temp_ebb_new_i64();
2103951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
2104951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2105951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
2106951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2107951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2108951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2109951c6300SRichard Henderson     }
2110951c6300SRichard Henderson }
2111951c6300SRichard Henderson 
211207dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2113951c6300SRichard Henderson {
211407dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2115951c6300SRichard Henderson     /* some cases can be optimized here */
2116951c6300SRichard Henderson     if (arg2 == 0) {
2117951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2118951c6300SRichard Henderson     } else {
2119951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
2120951c6300SRichard Henderson     }
2121951c6300SRichard Henderson }
2122951c6300SRichard Henderson 
2123951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
2124951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
2125951c6300SRichard Henderson {
2126951c6300SRichard Henderson     uint64_t mask;
2127951c6300SRichard Henderson     TCGv_i64 t1;
2128951c6300SRichard Henderson 
2129951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
21300d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2131951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2132951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2133951c6300SRichard Henderson 
21340d0d309dSRichard Henderson     if (len == 64) {
2135951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2136951c6300SRichard Henderson         return;
2137951c6300SRichard Henderson     }
2138951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2139951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2140951c6300SRichard Henderson         return;
2141951c6300SRichard Henderson     }
2142951c6300SRichard Henderson 
21433a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2144951c6300SRichard Henderson         if (ofs >= 32) {
2145951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2146951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2147951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2148951c6300SRichard Henderson             return;
2149951c6300SRichard Henderson         }
2150951c6300SRichard Henderson         if (ofs + len <= 32) {
2151951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2152951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2153951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2154951c6300SRichard Henderson             return;
2155951c6300SRichard Henderson         }
21563a13c3f3SRichard Henderson     }
2157951c6300SRichard Henderson 
21585dd48602SRichard Henderson     t1 = tcg_temp_ebb_new_i64();
2159951c6300SRichard Henderson 
2160b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i64) {
2161b0a60567SRichard Henderson         if (ofs + len == 64) {
2162b0a60567SRichard Henderson             tcg_gen_shli_i64(t1, arg1, len);
2163b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, t1, arg2, len);
2164b0a60567SRichard Henderson             goto done;
2165b0a60567SRichard Henderson         }
2166b0a60567SRichard Henderson         if (ofs == 0) {
2167b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, arg1, arg2, len);
2168b0a60567SRichard Henderson             tcg_gen_rotli_i64(ret, ret, len);
2169b0a60567SRichard Henderson             goto done;
2170b0a60567SRichard Henderson         }
2171b0a60567SRichard Henderson     }
2172b0a60567SRichard Henderson 
2173b0a60567SRichard Henderson     mask = (1ull << len) - 1;
2174951c6300SRichard Henderson     if (ofs + len < 64) {
2175951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2176951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2177951c6300SRichard Henderson     } else {
2178951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2179951c6300SRichard Henderson     }
2180951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2181951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2182b0a60567SRichard Henderson  done:
2183951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2184951c6300SRichard Henderson }
2185951c6300SRichard Henderson 
218607cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
218707cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
218807cc68d5SRichard Henderson {
218907cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
219007cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
219107cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
219207cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
219307cc68d5SRichard Henderson 
219407cc68d5SRichard Henderson     if (ofs + len == 64) {
219507cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
219607cc68d5SRichard Henderson     } else if (ofs == 0) {
219707cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
219807cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
219907cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
220011d11d61SRichard Henderson         TCGv_i64 zero = tcg_constant_i64(0);
220107cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
220207cc68d5SRichard Henderson     } else {
220307cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
220407cc68d5SRichard Henderson             if (ofs >= 32) {
220507cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
220607cc68d5SRichard Henderson                                       ofs - 32, len);
220707cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
220807cc68d5SRichard Henderson                 return;
220907cc68d5SRichard Henderson             }
221007cc68d5SRichard Henderson             if (ofs + len <= 32) {
221107cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
221207cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
221307cc68d5SRichard Henderson                 return;
221407cc68d5SRichard Henderson             }
221507cc68d5SRichard Henderson         }
221607cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
221707cc68d5SRichard Henderson            which allows ARG to stay live.  */
221807cc68d5SRichard Henderson         switch (len) {
221907cc68d5SRichard Henderson         case 32:
222007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
222107cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
222207cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
222307cc68d5SRichard Henderson                 return;
222407cc68d5SRichard Henderson             }
222507cc68d5SRichard Henderson             break;
222607cc68d5SRichard Henderson         case 16:
222707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
222807cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
222907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
223007cc68d5SRichard Henderson                 return;
223107cc68d5SRichard Henderson             }
223207cc68d5SRichard Henderson             break;
223307cc68d5SRichard Henderson         case 8:
223407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
223507cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
223607cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
223707cc68d5SRichard Henderson                 return;
223807cc68d5SRichard Henderson             }
223907cc68d5SRichard Henderson             break;
224007cc68d5SRichard Henderson         }
224107cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
224207cc68d5SRichard Henderson         switch (ofs + len) {
224307cc68d5SRichard Henderson         case 32:
224407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
224507cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
224607cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
224707cc68d5SRichard Henderson                 return;
224807cc68d5SRichard Henderson             }
224907cc68d5SRichard Henderson             break;
225007cc68d5SRichard Henderson         case 16:
225107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
225207cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
225307cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
225407cc68d5SRichard Henderson                 return;
225507cc68d5SRichard Henderson             }
225607cc68d5SRichard Henderson             break;
225707cc68d5SRichard Henderson         case 8:
225807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
225907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
226007cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
226107cc68d5SRichard Henderson                 return;
226207cc68d5SRichard Henderson             }
226307cc68d5SRichard Henderson             break;
226407cc68d5SRichard Henderson         }
226507cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
226607cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
226707cc68d5SRichard Henderson     }
226807cc68d5SRichard Henderson }
226907cc68d5SRichard Henderson 
22707ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
22717ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
22727ec8bab3SRichard Henderson {
22737ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22747ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22757ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22767ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22777ec8bab3SRichard Henderson 
22787ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
22797ec8bab3SRichard Henderson     if (ofs + len == 64) {
22807ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
22817ec8bab3SRichard Henderson         return;
22827ec8bab3SRichard Henderson     }
22837ec8bab3SRichard Henderson     if (ofs == 0) {
22847ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
22857ec8bab3SRichard Henderson         return;
22867ec8bab3SRichard Henderson     }
22877ec8bab3SRichard Henderson 
22887ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22897ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22907ec8bab3SRichard Henderson         if (ofs >= 32) {
22917ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22927ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22937ec8bab3SRichard Henderson             return;
22947ec8bab3SRichard Henderson         }
22957ec8bab3SRichard Henderson         if (ofs + len <= 32) {
22967ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22977ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22987ec8bab3SRichard Henderson             return;
22997ec8bab3SRichard Henderson         }
23007ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
23017ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
23027ec8bab3SRichard Henderson         goto do_shift_and;
23037ec8bab3SRichard Henderson     }
23047ec8bab3SRichard Henderson 
23057ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
23067ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
23077ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
23087ec8bab3SRichard Henderson         return;
23097ec8bab3SRichard Henderson     }
23107ec8bab3SRichard Henderson 
23117ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
23127ec8bab3SRichard Henderson     switch (ofs + len) {
23137ec8bab3SRichard Henderson     case 32:
23147ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
23157ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
23167ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
23177ec8bab3SRichard Henderson             return;
23187ec8bab3SRichard Henderson         }
23197ec8bab3SRichard Henderson         break;
23207ec8bab3SRichard Henderson     case 16:
23217ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
23227ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
23237ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
23247ec8bab3SRichard Henderson             return;
23257ec8bab3SRichard Henderson         }
23267ec8bab3SRichard Henderson         break;
23277ec8bab3SRichard Henderson     case 8:
23287ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
23297ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
23307ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
23317ec8bab3SRichard Henderson             return;
23327ec8bab3SRichard Henderson         }
23337ec8bab3SRichard Henderson         break;
23347ec8bab3SRichard Henderson     }
23357ec8bab3SRichard Henderson 
23367ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
23377ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
23387ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
23397ec8bab3SRichard Henderson     switch (len) {
23407ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
23417ec8bab3SRichard Henderson     do_shift_and:
23427ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
23437ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
23447ec8bab3SRichard Henderson         break;
23457ec8bab3SRichard Henderson     default:
23467ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23477ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
23487ec8bab3SRichard Henderson         break;
23497ec8bab3SRichard Henderson     }
23507ec8bab3SRichard Henderson }
23517ec8bab3SRichard Henderson 
23527ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
23537ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
23547ec8bab3SRichard Henderson {
23557ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
23567ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
23577ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
23587ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
23597ec8bab3SRichard Henderson 
23607ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
23617ec8bab3SRichard Henderson     if (ofs + len == 64) {
23627ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
23637ec8bab3SRichard Henderson         return;
23647ec8bab3SRichard Henderson     }
23657ec8bab3SRichard Henderson     if (ofs == 0) {
23667ec8bab3SRichard Henderson         switch (len) {
23677ec8bab3SRichard Henderson         case 32:
23687ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
23697ec8bab3SRichard Henderson             return;
23707ec8bab3SRichard Henderson         case 16:
23717ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23727ec8bab3SRichard Henderson             return;
23737ec8bab3SRichard Henderson         case 8:
23747ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23757ec8bab3SRichard Henderson             return;
23767ec8bab3SRichard Henderson         }
23777ec8bab3SRichard Henderson     }
23787ec8bab3SRichard Henderson 
23797ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
23807ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
23817ec8bab3SRichard Henderson         if (ofs >= 32) {
23827ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
23837ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
23847ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
23857ec8bab3SRichard Henderson         } else if (ofs == 0) {
23867ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
23877ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
23887ec8bab3SRichard Henderson             return;
23897ec8bab3SRichard Henderson         } else if (len > 32) {
23905dd48602SRichard Henderson             TCGv_i32 t = tcg_temp_ebb_new_i32();
23917ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
23927ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
23937ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
23947ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23957ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
23967ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
23977ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
23987ec8bab3SRichard Henderson             return;
23997ec8bab3SRichard Henderson         } else {
24007ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
24017ec8bab3SRichard Henderson                field sits at the MSB.  */
24027ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
24037ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
24047ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
24057ec8bab3SRichard Henderson         }
24067ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
24077ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
24087ec8bab3SRichard Henderson         return;
24097ec8bab3SRichard Henderson     }
24107ec8bab3SRichard Henderson 
24117ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
24127ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
24137ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
24147ec8bab3SRichard Henderson         return;
24157ec8bab3SRichard Henderson     }
24167ec8bab3SRichard Henderson 
24177ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
24187ec8bab3SRichard Henderson     switch (ofs + len) {
24197ec8bab3SRichard Henderson     case 32:
24207ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
24217ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
24227ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
24237ec8bab3SRichard Henderson             return;
24247ec8bab3SRichard Henderson         }
24257ec8bab3SRichard Henderson         break;
24267ec8bab3SRichard Henderson     case 16:
24277ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
24287ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
24297ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
24307ec8bab3SRichard Henderson             return;
24317ec8bab3SRichard Henderson         }
24327ec8bab3SRichard Henderson         break;
24337ec8bab3SRichard Henderson     case 8:
24347ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
24357ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
24367ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
24377ec8bab3SRichard Henderson             return;
24387ec8bab3SRichard Henderson         }
24397ec8bab3SRichard Henderson         break;
24407ec8bab3SRichard Henderson     }
24417ec8bab3SRichard Henderson     switch (len) {
24427ec8bab3SRichard Henderson     case 32:
24437ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
24447ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24457ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
24467ec8bab3SRichard Henderson             return;
24477ec8bab3SRichard Henderson         }
24487ec8bab3SRichard Henderson         break;
24497ec8bab3SRichard Henderson     case 16:
24507ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
24517ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24527ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
24537ec8bab3SRichard Henderson             return;
24547ec8bab3SRichard Henderson         }
24557ec8bab3SRichard Henderson         break;
24567ec8bab3SRichard Henderson     case 8:
24577ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
24587ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24597ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
24607ec8bab3SRichard Henderson             return;
24617ec8bab3SRichard Henderson         }
24627ec8bab3SRichard Henderson         break;
24637ec8bab3SRichard Henderson     }
24647ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
24657ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
24667ec8bab3SRichard Henderson }
24677ec8bab3SRichard Henderson 
24682089fcc9SDavid Hildenbrand /*
24692089fcc9SDavid Hildenbrand  * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
24702089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
24712089fcc9SDavid Hildenbrand  */
24722089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
24732089fcc9SDavid Hildenbrand                           unsigned int ofs)
24742089fcc9SDavid Hildenbrand {
24752089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 64);
24762089fcc9SDavid Hildenbrand     if (ofs == 0) {
24772089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, al);
24782089fcc9SDavid Hildenbrand     } else if (ofs == 64) {
24792089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, ah);
24802089fcc9SDavid Hildenbrand     } else if (al == ah) {
24812089fcc9SDavid Hildenbrand         tcg_gen_rotri_i64(ret, al, ofs);
2482fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i64) {
2483fce1296fSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
24842089fcc9SDavid Hildenbrand     } else {
24855dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
24862089fcc9SDavid Hildenbrand         tcg_gen_shri_i64(t0, al, ofs);
24872089fcc9SDavid Hildenbrand         tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs);
24882089fcc9SDavid Hildenbrand         tcg_temp_free_i64(t0);
24892089fcc9SDavid Hildenbrand     }
24902089fcc9SDavid Hildenbrand }
24912089fcc9SDavid Hildenbrand 
2492951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2493951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2494951c6300SRichard Henderson {
249537ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
249637ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
249737ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
249837ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
249937ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
25005dd48602SRichard Henderson         TCGv_i32 t0 = tcg_temp_ebb_new_i32();
25015dd48602SRichard Henderson         TCGv_i32 t1 = tcg_temp_ebb_new_i32();
2502951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2503951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2504951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2505951c6300SRichard Henderson 
2506951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2507951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2508951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2509951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2510951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2511951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2512951c6300SRichard Henderson         } else {
2513951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2514951c6300SRichard Henderson 
2515951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2516951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2517951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2518951c6300SRichard Henderson 
2519951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2520951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2521951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2522951c6300SRichard Henderson         }
2523951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2524951c6300SRichard Henderson         tcg_temp_free_i32(t1);
25253a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2526951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2527951c6300SRichard Henderson     } else {
25285dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
25295dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2530951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2531951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2532951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2533951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2534951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2535951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2536951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2537951c6300SRichard Henderson     }
2538951c6300SRichard Henderson }
2539951c6300SRichard Henderson 
2540951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2541951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2542951c6300SRichard Henderson {
2543951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2544951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2545951c6300SRichard Henderson     } else {
25465dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
25475dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2548951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2549951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2550951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2551951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2552951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2553951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2554951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2555951c6300SRichard Henderson     }
2556951c6300SRichard Henderson }
2557951c6300SRichard Henderson 
2558951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2559951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2560951c6300SRichard Henderson {
2561951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2562951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2563951c6300SRichard Henderson     } else {
25645dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
25655dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2566951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2567951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2568951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2569951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2570951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2571951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2572951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2573951c6300SRichard Henderson     }
2574951c6300SRichard Henderson }
2575951c6300SRichard Henderson 
2576951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2577951c6300SRichard Henderson {
2578951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2579951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2580951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
25815dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2582951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2583951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2584951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2585951c6300SRichard Henderson         tcg_temp_free_i64(t);
2586951c6300SRichard Henderson     } else {
25875dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2588951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2589951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2590951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2591951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2592951c6300SRichard Henderson     }
2593951c6300SRichard Henderson }
2594951c6300SRichard Henderson 
2595951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2596951c6300SRichard Henderson {
2597951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2598951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2599951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
26005dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2601951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2602951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2603951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2604951c6300SRichard Henderson         tcg_temp_free_i64(t);
2605951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
26065dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
26075dd48602SRichard Henderson         TCGv_i64 t1 = tcg_temp_ebb_new_i64();
26085dd48602SRichard Henderson         TCGv_i64 t2 = tcg_temp_ebb_new_i64();
26095dd48602SRichard Henderson         TCGv_i64 t3 = tcg_temp_ebb_new_i64();
2610951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2611951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2612951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2613951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2614951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2615951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2616951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2617951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2618951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2619951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2620951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2621951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2622951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2623951c6300SRichard Henderson     } else {
26245dd48602SRichard Henderson         TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2625951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2626951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2627951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2628951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2629951c6300SRichard Henderson     }
2630951c6300SRichard Henderson }
2631951c6300SRichard Henderson 
26325087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
26335087abfbSRichard Henderson {
26345dd48602SRichard Henderson     TCGv_i64 t0 = tcg_temp_ebb_new_i64();
26355dd48602SRichard Henderson     TCGv_i64 t1 = tcg_temp_ebb_new_i64();
26365dd48602SRichard Henderson     TCGv_i64 t2 = tcg_temp_ebb_new_i64();
26375087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
26385087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
26395087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
26405087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
26415087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
26425087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
26435087abfbSRichard Henderson     tcg_temp_free_i64(t0);
26445087abfbSRichard Henderson     tcg_temp_free_i64(t1);
26455087abfbSRichard Henderson     tcg_temp_free_i64(t2);
26465087abfbSRichard Henderson }
26475087abfbSRichard Henderson 
2648b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2649b87fb8cdSRichard Henderson {
2650b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2651b87fb8cdSRichard Henderson }
2652b87fb8cdSRichard Henderson 
2653b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2654b87fb8cdSRichard Henderson {
2655b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2656b87fb8cdSRichard Henderson }
2657b87fb8cdSRichard Henderson 
2658b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2659b87fb8cdSRichard Henderson {
2660b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2661b87fb8cdSRichard Henderson }
2662b87fb8cdSRichard Henderson 
2663b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2664b87fb8cdSRichard Henderson {
2665b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2666b87fb8cdSRichard Henderson }
2667b87fb8cdSRichard Henderson 
2668ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
2669ff1f11f7SRichard Henderson {
26705dd48602SRichard Henderson     TCGv_i64 t = tcg_temp_ebb_new_i64();
2671ff1f11f7SRichard Henderson 
2672ff1f11f7SRichard Henderson     tcg_gen_sari_i64(t, a, 63);
2673ff1f11f7SRichard Henderson     tcg_gen_xor_i64(ret, a, t);
2674ff1f11f7SRichard Henderson     tcg_gen_sub_i64(ret, ret, t);
2675ff1f11f7SRichard Henderson     tcg_temp_free_i64(t);
2676ff1f11f7SRichard Henderson }
2677ff1f11f7SRichard Henderson 
2678951c6300SRichard Henderson /* Size changing operations.  */
2679951c6300SRichard Henderson 
2680609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2681951c6300SRichard Henderson {
26823a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2683951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2684609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2685b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2686ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2687951c6300SRichard Henderson     } else {
2688dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2689609ad705SRichard Henderson     }
2690609ad705SRichard Henderson }
2691609ad705SRichard Henderson 
2692609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2693609ad705SRichard Henderson {
2694609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2695609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2696609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2697b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2698ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2699951c6300SRichard Henderson     } else {
27005dd48602SRichard Henderson         TCGv_i64 t = tcg_temp_ebb_new_i64();
2701609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2702dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2703951c6300SRichard Henderson         tcg_temp_free_i64(t);
2704951c6300SRichard Henderson     }
2705951c6300SRichard Henderson }
2706951c6300SRichard Henderson 
2707951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2708951c6300SRichard Henderson {
27093a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2710951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2711951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
27123a13c3f3SRichard Henderson     } else {
2713b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2714ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
27153a13c3f3SRichard Henderson     }
2716951c6300SRichard Henderson }
2717951c6300SRichard Henderson 
2718951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2719951c6300SRichard Henderson {
27203a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2721951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2722951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
27233a13c3f3SRichard Henderson     } else {
2724b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2725ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
27263a13c3f3SRichard Henderson     }
2727951c6300SRichard Henderson }
2728951c6300SRichard Henderson 
2729951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2730951c6300SRichard Henderson {
27313a13c3f3SRichard Henderson     TCGv_i64 tmp;
27323a13c3f3SRichard Henderson 
27333a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2734951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2735951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
27363a13c3f3SRichard Henderson         return;
27373a13c3f3SRichard Henderson     }
27383a13c3f3SRichard Henderson 
27395dd48602SRichard Henderson     tmp = tcg_temp_ebb_new_i64();
2740951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2741951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2742951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2743951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2744951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2745951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2746951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2747951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2748951c6300SRichard Henderson     } else {
2749951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2750951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2751951c6300SRichard Henderson     }
2752951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2753951c6300SRichard Henderson }
2754951c6300SRichard Henderson 
2755951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2756951c6300SRichard Henderson {
27573a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2758951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2759951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
27603a13c3f3SRichard Henderson     } else {
2761609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2762609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
27633a13c3f3SRichard Henderson     }
2764951c6300SRichard Henderson }
2765951c6300SRichard Henderson 
2766951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2767951c6300SRichard Henderson {
2768951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2769951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2770951c6300SRichard Henderson }
2771951c6300SRichard Henderson 
27724771e71cSRichard Henderson void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg)
27734771e71cSRichard Henderson {
27744771e71cSRichard Henderson     tcg_gen_mov_i64(lo, TCGV128_LOW(arg));
27754771e71cSRichard Henderson     tcg_gen_mov_i64(hi, TCGV128_HIGH(arg));
27764771e71cSRichard Henderson }
27774771e71cSRichard Henderson 
27784771e71cSRichard Henderson void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi)
27794771e71cSRichard Henderson {
27804771e71cSRichard Henderson     tcg_gen_mov_i64(TCGV128_LOW(ret), lo);
27814771e71cSRichard Henderson     tcg_gen_mov_i64(TCGV128_HIGH(ret), hi);
27824771e71cSRichard Henderson }
27834771e71cSRichard Henderson 
27844771e71cSRichard Henderson void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src)
27854771e71cSRichard Henderson {
27864771e71cSRichard Henderson     if (dst != src) {
27874771e71cSRichard Henderson         tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src));
27884771e71cSRichard Henderson         tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src));
27894771e71cSRichard Henderson     }
27904771e71cSRichard Henderson }
27914771e71cSRichard Henderson 
2792951c6300SRichard Henderson /* QEMU specific operations.  */
2793951c6300SRichard Henderson 
2794d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
279507ea28b4SRichard Henderson {
2796eba40358SRichard Henderson     /*
2797eba40358SRichard Henderson      * Let the jit code return the read-only version of the
2798eba40358SRichard Henderson      * TranslationBlock, so that we minimize the pc-relative
2799eba40358SRichard Henderson      * distance of the address of the exit_tb code to TB.
2800eba40358SRichard Henderson      * This will improve utilization of pc-relative address loads.
2801eba40358SRichard Henderson      *
2802eba40358SRichard Henderson      * TODO: Move this to translator_loop, so that all const
2803eba40358SRichard Henderson      * TranslationBlock pointers refer to read-only memory.
2804eba40358SRichard Henderson      * This requires coordination with targets that do not use
2805eba40358SRichard Henderson      * the translator_loop.
2806eba40358SRichard Henderson      */
2807eba40358SRichard Henderson     uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx;
280807ea28b4SRichard Henderson 
280907ea28b4SRichard Henderson     if (tb == NULL) {
281007ea28b4SRichard Henderson         tcg_debug_assert(idx == 0);
281107ea28b4SRichard Henderson     } else if (idx <= TB_EXIT_IDXMAX) {
281207ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG
281307ea28b4SRichard Henderson         /* This is an exit following a goto_tb.  Verify that we have
281407ea28b4SRichard Henderson            seen this numbered exit before, via tcg_gen_goto_tb.  */
281507ea28b4SRichard Henderson         tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
281607ea28b4SRichard Henderson #endif
281707ea28b4SRichard Henderson     } else {
281807ea28b4SRichard Henderson         /* This is an exit via the exitreq label.  */
281907ea28b4SRichard Henderson         tcg_debug_assert(idx == TB_EXIT_REQUESTED);
282007ea28b4SRichard Henderson     }
282107ea28b4SRichard Henderson 
282207ea28b4SRichard Henderson     tcg_gen_op1i(INDEX_op_exit_tb, val);
282307ea28b4SRichard Henderson }
282407ea28b4SRichard Henderson 
2825951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2826951c6300SRichard Henderson {
282784f15616SRichard Henderson     /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
2828b7e4afbdSRichard Henderson     tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB));
2829951c6300SRichard Henderson     /* We only support two chained exits.  */
283007ea28b4SRichard Henderson     tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
2831951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2832a4761232SPhilippe Mathieu-Daudé     /* Verify that we haven't seen this numbered exit before.  */
2833b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2834b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2835951c6300SRichard Henderson #endif
2836e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2837951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2838951c6300SRichard Henderson }
2839951c6300SRichard Henderson 
28407f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2841cedbcb01SEmilio G. Cota {
2842e6d86bedSEmilio G. Cota     TCGv_ptr ptr;
2843e6d86bedSEmilio G. Cota 
2844b7e4afbdSRichard Henderson     if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) {
284584f15616SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
284684f15616SRichard Henderson         return;
284784f15616SRichard Henderson     }
284884f15616SRichard Henderson 
2849e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
28505dd48602SRichard Henderson     ptr = tcg_temp_ebb_new_ptr();
28511c2adb95SRichard Henderson     gen_helper_lookup_tb_ptr(ptr, cpu_env);
2852ae8b75dcSRichard Henderson     tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2853cedbcb01SEmilio G. Cota     tcg_temp_free_ptr(ptr);
2854cedbcb01SEmilio G. Cota }
2855