xref: /openbmc/qemu/tcg/tcg-op.c (revision 76e366e7)
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"
2663c91552SPaolo Bonzini #include "exec/exec-all.h"
27dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h"
28dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
29dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-mo.h"
30dcdaadb6SLluís Vilanova #include "trace-tcg.h"
31e6d86bedSEmilio G. Cota #include "exec/plugin-gen.h"
32951c6300SRichard Henderson 
333a13c3f3SRichard Henderson /* Reduce the number of ifdefs below.  This assumes that all uses of
343a13c3f3SRichard Henderson    TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
353a13c3f3SRichard Henderson    the compiler can eliminate.  */
363a13c3f3SRichard Henderson #if TCG_TARGET_REG_BITS == 64
373a13c3f3SRichard Henderson extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
383a13c3f3SRichard Henderson extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
393a13c3f3SRichard Henderson #define TCGV_LOW  TCGV_LOW_link_error
403a13c3f3SRichard Henderson #define TCGV_HIGH TCGV_HIGH_link_error
413a13c3f3SRichard Henderson #endif
42951c6300SRichard Henderson 
43b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
44951c6300SRichard Henderson {
45b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
4675e8b9b7SRichard Henderson     op->args[0] = a1;
47951c6300SRichard Henderson }
48951c6300SRichard Henderson 
49b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
50951c6300SRichard Henderson {
51b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
5275e8b9b7SRichard Henderson     op->args[0] = a1;
5375e8b9b7SRichard Henderson     op->args[1] = a2;
54951c6300SRichard Henderson }
55951c6300SRichard Henderson 
56b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
57951c6300SRichard Henderson {
58b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
5975e8b9b7SRichard Henderson     op->args[0] = a1;
6075e8b9b7SRichard Henderson     op->args[1] = a2;
6175e8b9b7SRichard Henderson     op->args[2] = a3;
62951c6300SRichard Henderson }
63951c6300SRichard Henderson 
64b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
65951c6300SRichard Henderson {
66b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
6775e8b9b7SRichard Henderson     op->args[0] = a1;
6875e8b9b7SRichard Henderson     op->args[1] = a2;
6975e8b9b7SRichard Henderson     op->args[2] = a3;
7075e8b9b7SRichard Henderson     op->args[3] = a4;
71951c6300SRichard Henderson }
72951c6300SRichard Henderson 
73b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
74b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5)
75951c6300SRichard Henderson {
76b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
7775e8b9b7SRichard Henderson     op->args[0] = a1;
7875e8b9b7SRichard Henderson     op->args[1] = a2;
7975e8b9b7SRichard Henderson     op->args[2] = a3;
8075e8b9b7SRichard Henderson     op->args[3] = a4;
8175e8b9b7SRichard Henderson     op->args[4] = a5;
82951c6300SRichard Henderson }
83951c6300SRichard Henderson 
84b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
85b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5, TCGArg a6)
86951c6300SRichard Henderson {
87b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
8875e8b9b7SRichard Henderson     op->args[0] = a1;
8975e8b9b7SRichard Henderson     op->args[1] = a2;
9075e8b9b7SRichard Henderson     op->args[2] = a3;
9175e8b9b7SRichard Henderson     op->args[3] = a4;
9275e8b9b7SRichard Henderson     op->args[4] = a5;
9375e8b9b7SRichard Henderson     op->args[5] = a6;
94951c6300SRichard Henderson }
95951c6300SRichard Henderson 
96f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
97f65e19bcSPranith Kumar {
98b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {
99b7e8b17aSRichard Henderson         tcg_gen_op1(INDEX_op_mb, mb_type);
100f65e19bcSPranith Kumar     }
101f65e19bcSPranith Kumar }
102f65e19bcSPranith Kumar 
103951c6300SRichard Henderson /* 32 bit ops */
104951c6300SRichard Henderson 
10511d11d61SRichard Henderson void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
10611d11d61SRichard Henderson {
10711d11d61SRichard Henderson     tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
10811d11d61SRichard Henderson }
10911d11d61SRichard Henderson 
110951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
111951c6300SRichard Henderson {
112951c6300SRichard Henderson     /* some cases can be optimized here */
113951c6300SRichard Henderson     if (arg2 == 0) {
114951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
115951c6300SRichard Henderson     } else {
11611d11d61SRichard Henderson         tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
117951c6300SRichard Henderson     }
118951c6300SRichard Henderson }
119951c6300SRichard Henderson 
120951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
121951c6300SRichard Henderson {
122951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
123951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
124951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
125951c6300SRichard Henderson     } else {
12611d11d61SRichard Henderson         tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
127951c6300SRichard Henderson     }
128951c6300SRichard Henderson }
129951c6300SRichard Henderson 
130951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
131951c6300SRichard Henderson {
132951c6300SRichard Henderson     /* some cases can be optimized here */
133951c6300SRichard Henderson     if (arg2 == 0) {
134951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
135951c6300SRichard Henderson     } else {
13611d11d61SRichard Henderson         tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
137951c6300SRichard Henderson     }
138951c6300SRichard Henderson }
139951c6300SRichard Henderson 
140474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
141951c6300SRichard Henderson {
142951c6300SRichard Henderson     /* Some cases can be optimized here.  */
143951c6300SRichard Henderson     switch (arg2) {
144951c6300SRichard Henderson     case 0:
145951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
146951c6300SRichard Henderson         return;
147474b2e8fSRichard Henderson     case -1:
148951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
149951c6300SRichard Henderson         return;
150474b2e8fSRichard Henderson     case 0xff:
151951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
152951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
153951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
154951c6300SRichard Henderson             return;
155951c6300SRichard Henderson         }
156951c6300SRichard Henderson         break;
157474b2e8fSRichard Henderson     case 0xffff:
158951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
159951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
160951c6300SRichard Henderson             return;
161951c6300SRichard Henderson         }
162951c6300SRichard Henderson         break;
163951c6300SRichard Henderson     }
16411d11d61SRichard Henderson 
16511d11d61SRichard Henderson     tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
166951c6300SRichard Henderson }
167951c6300SRichard Henderson 
168951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
169951c6300SRichard Henderson {
170951c6300SRichard Henderson     /* Some cases can be optimized here.  */
171951c6300SRichard Henderson     if (arg2 == -1) {
172951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
173951c6300SRichard Henderson     } else if (arg2 == 0) {
174951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
175951c6300SRichard Henderson     } else {
17611d11d61SRichard Henderson         tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
177951c6300SRichard Henderson     }
178951c6300SRichard Henderson }
179951c6300SRichard Henderson 
180951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
181951c6300SRichard Henderson {
182951c6300SRichard Henderson     /* Some cases can be optimized here.  */
183951c6300SRichard Henderson     if (arg2 == 0) {
184951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
185951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
186951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
187951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
188951c6300SRichard Henderson     } else {
18911d11d61SRichard Henderson         tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
190951c6300SRichard Henderson     }
191951c6300SRichard Henderson }
192951c6300SRichard Henderson 
193474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
194951c6300SRichard Henderson {
195474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
196951c6300SRichard Henderson     if (arg2 == 0) {
197951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
198951c6300SRichard Henderson     } else {
19911d11d61SRichard Henderson         tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2));
200951c6300SRichard Henderson     }
201951c6300SRichard Henderson }
202951c6300SRichard Henderson 
203474b2e8fSRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
204951c6300SRichard Henderson {
205474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
206951c6300SRichard Henderson     if (arg2 == 0) {
207951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
208951c6300SRichard Henderson     } else {
20911d11d61SRichard Henderson         tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2));
210951c6300SRichard Henderson     }
211951c6300SRichard Henderson }
212951c6300SRichard Henderson 
213474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
214951c6300SRichard Henderson {
215474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
216951c6300SRichard Henderson     if (arg2 == 0) {
217951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
218951c6300SRichard Henderson     } else {
21911d11d61SRichard Henderson         tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2));
220951c6300SRichard Henderson     }
221951c6300SRichard Henderson }
222951c6300SRichard Henderson 
22342a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
224951c6300SRichard Henderson {
225951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
22642a268c2SRichard Henderson         tcg_gen_br(l);
227951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
228d88a117eSRichard Henderson         l->refs++;
22942a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
230951c6300SRichard Henderson     }
231951c6300SRichard Henderson }
232951c6300SRichard Henderson 
23342a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
234951c6300SRichard Henderson {
23537ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
23637ed3bf1SRichard Henderson         tcg_gen_br(l);
23737ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
23811d11d61SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l);
239951c6300SRichard Henderson     }
24037ed3bf1SRichard Henderson }
241951c6300SRichard Henderson 
242951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
243951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
244951c6300SRichard Henderson {
245951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
246951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
247951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
248951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
249951c6300SRichard Henderson     } else {
250951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
251951c6300SRichard Henderson     }
252951c6300SRichard Henderson }
253951c6300SRichard Henderson 
254951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
255951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
256951c6300SRichard Henderson {
25711d11d61SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2));
258951c6300SRichard Henderson }
259951c6300SRichard Henderson 
260951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
261951c6300SRichard Henderson {
262b2e3ae94SRichard Henderson     if (arg2 == 0) {
263b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
264b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
265b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
266b2e3ae94SRichard Henderson     } else {
26711d11d61SRichard Henderson         tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2));
268951c6300SRichard Henderson     }
269b2e3ae94SRichard Henderson }
270951c6300SRichard Henderson 
271951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
272951c6300SRichard Henderson {
273951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
274951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
275951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
276951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
277951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
278951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
279951c6300SRichard Henderson         tcg_temp_free_i32(t0);
280951c6300SRichard Henderson     } else {
281951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
282951c6300SRichard Henderson     }
283951c6300SRichard Henderson }
284951c6300SRichard Henderson 
285951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
286951c6300SRichard Henderson {
287951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
288951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
289951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
290951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
291951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
292951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
293951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
294951c6300SRichard Henderson         tcg_temp_free_i32(t0);
295951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
296951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
297951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
298951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
299951c6300SRichard Henderson         tcg_temp_free_i32(t0);
300951c6300SRichard Henderson     } else {
301951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
302951c6300SRichard Henderson     }
303951c6300SRichard Henderson }
304951c6300SRichard Henderson 
305951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
306951c6300SRichard Henderson {
307951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
308951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
309951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
310951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
311951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
312951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
313951c6300SRichard Henderson         tcg_temp_free_i32(t0);
314951c6300SRichard Henderson     } else {
315951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
316951c6300SRichard Henderson     }
317951c6300SRichard Henderson }
318951c6300SRichard Henderson 
319951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
320951c6300SRichard Henderson {
321951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
322951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
323951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
324951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
325951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
326951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
327951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
328951c6300SRichard Henderson         tcg_temp_free_i32(t0);
329951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
330951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
331951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
332951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
333951c6300SRichard Henderson         tcg_temp_free_i32(t0);
334951c6300SRichard Henderson     } else {
335951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
336951c6300SRichard Henderson     }
337951c6300SRichard Henderson }
338951c6300SRichard Henderson 
339951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
340951c6300SRichard Henderson {
341951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
342951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
343951c6300SRichard Henderson     } else {
344951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
345951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
346951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
347951c6300SRichard Henderson         tcg_temp_free_i32(t0);
348951c6300SRichard Henderson     }
349951c6300SRichard Henderson }
350951c6300SRichard Henderson 
351951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
352951c6300SRichard Henderson {
353951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
354951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
355951c6300SRichard Henderson     } else {
356951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
357951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
358951c6300SRichard Henderson     }
359951c6300SRichard Henderson }
360951c6300SRichard Henderson 
361951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
362951c6300SRichard Henderson {
363951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
364951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
365951c6300SRichard Henderson     } else {
366951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
367951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
368951c6300SRichard Henderson     }
369951c6300SRichard Henderson }
370951c6300SRichard Henderson 
371951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
372951c6300SRichard Henderson {
373951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
374951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
375951c6300SRichard Henderson     } else {
376951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
377951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
378951c6300SRichard Henderson     }
379951c6300SRichard Henderson }
380951c6300SRichard Henderson 
381951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
382951c6300SRichard Henderson {
383951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
384951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
385951c6300SRichard Henderson     } else {
386951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
387951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
388951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
389951c6300SRichard Henderson         tcg_temp_free_i32(t0);
390951c6300SRichard Henderson     }
391951c6300SRichard Henderson }
392951c6300SRichard Henderson 
3930e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
3940e28d006SRichard Henderson {
3950e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
3960e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
3970e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
3980e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
3990e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4000e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4010e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4020e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4030e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4040e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4050e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4060e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4070e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4080e28d006SRichard Henderson     } else {
4090e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4100e28d006SRichard Henderson     }
4110e28d006SRichard Henderson }
4120e28d006SRichard Henderson 
4130e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4140e28d006SRichard Henderson {
41511d11d61SRichard Henderson     tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2));
4160e28d006SRichard Henderson }
4170e28d006SRichard Henderson 
4180e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4190e28d006SRichard Henderson {
4200e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4210e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4220e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4230e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4240e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4250e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4260e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4270e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4280e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4290e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4300e28d006SRichard Henderson         tcg_temp_free_i64(t2);
43114e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
43214e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
43314e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
43414e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
43514e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
43614e99210SRichard Henderson 
43714e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
43814e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
43914e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
44014e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
44114e99210SRichard Henderson         } else {
44214e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
44314e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
44414e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
44514e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
44614e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
44714e99210SRichard Henderson         }
44811d11d61SRichard Henderson         z = tcg_constant_i32(0);
44914e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
45014e99210SRichard Henderson         tcg_temp_free_i32(t);
4510e28d006SRichard Henderson     } else {
4520e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4530e28d006SRichard Henderson     }
4540e28d006SRichard Henderson }
4550e28d006SRichard Henderson 
4560e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4570e28d006SRichard Henderson {
45814e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
45914e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
46014e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
46114e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
46214e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
46314e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
46414e99210SRichard Henderson         tcg_temp_free_i32(t);
46514e99210SRichard Henderson     } else {
46611d11d61SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2));
4670e28d006SRichard Henderson     }
46814e99210SRichard Henderson }
4690e28d006SRichard Henderson 
470086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
471086920c2SRichard Henderson {
472086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
473086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
474086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
475086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
476086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
477086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
478086920c2SRichard Henderson         tcg_temp_free_i32(t);
479086920c2SRichard Henderson     } else {
480086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
481086920c2SRichard Henderson     }
482086920c2SRichard Henderson }
483086920c2SRichard Henderson 
484a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
485a768e4e9SRichard Henderson {
486a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
487a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
488a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
489a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
490a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
491a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
492a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
493a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
494a768e4e9SRichard Henderson     } else {
495a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
496a768e4e9SRichard Henderson     }
497a768e4e9SRichard Henderson }
498a768e4e9SRichard Henderson 
499951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
500951c6300SRichard Henderson {
501951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
502951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
503951c6300SRichard Henderson     } else {
504951c6300SRichard Henderson         TCGv_i32 t0, t1;
505951c6300SRichard Henderson 
506951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
507951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
508951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
509951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
510951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
511951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
512951c6300SRichard Henderson         tcg_temp_free_i32(t0);
513951c6300SRichard Henderson         tcg_temp_free_i32(t1);
514951c6300SRichard Henderson     }
515951c6300SRichard Henderson }
516951c6300SRichard Henderson 
51707dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
518951c6300SRichard Henderson {
51907dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
520951c6300SRichard Henderson     /* some cases can be optimized here */
521951c6300SRichard Henderson     if (arg2 == 0) {
522951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
523951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
52411d11d61SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2));
525951c6300SRichard Henderson     } else {
526951c6300SRichard Henderson         TCGv_i32 t0, t1;
527951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
528951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
529951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
530951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
531951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
532951c6300SRichard Henderson         tcg_temp_free_i32(t0);
533951c6300SRichard Henderson         tcg_temp_free_i32(t1);
534951c6300SRichard Henderson     }
535951c6300SRichard Henderson }
536951c6300SRichard Henderson 
537951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
538951c6300SRichard Henderson {
539951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
540951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
541951c6300SRichard Henderson     } else {
542951c6300SRichard Henderson         TCGv_i32 t0, t1;
543951c6300SRichard Henderson 
544951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
545951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
546951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
547951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
548951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
549951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
550951c6300SRichard Henderson         tcg_temp_free_i32(t0);
551951c6300SRichard Henderson         tcg_temp_free_i32(t1);
552951c6300SRichard Henderson     }
553951c6300SRichard Henderson }
554951c6300SRichard Henderson 
55507dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
556951c6300SRichard Henderson {
55707dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
558951c6300SRichard Henderson     /* some cases can be optimized here */
559951c6300SRichard Henderson     if (arg2 == 0) {
560951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
561951c6300SRichard Henderson     } else {
562951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
563951c6300SRichard Henderson     }
564951c6300SRichard Henderson }
565951c6300SRichard Henderson 
566951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
567951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
568951c6300SRichard Henderson {
569951c6300SRichard Henderson     uint32_t mask;
570951c6300SRichard Henderson     TCGv_i32 t1;
571951c6300SRichard Henderson 
572951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
5730d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
574951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
575951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
576951c6300SRichard Henderson 
5770d0d309dSRichard Henderson     if (len == 32) {
578951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
579951c6300SRichard Henderson         return;
580951c6300SRichard Henderson     }
581951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
582951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
583951c6300SRichard Henderson         return;
584951c6300SRichard Henderson     }
585951c6300SRichard Henderson 
586951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
587951c6300SRichard Henderson 
588b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i32) {
589b0a60567SRichard Henderson         if (ofs + len == 32) {
590b0a60567SRichard Henderson             tcg_gen_shli_i32(t1, arg1, len);
591b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, t1, arg2, len);
592b0a60567SRichard Henderson             goto done;
593b0a60567SRichard Henderson         }
594b0a60567SRichard Henderson         if (ofs == 0) {
595b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, arg1, arg2, len);
596b0a60567SRichard Henderson             tcg_gen_rotli_i32(ret, ret, len);
597b0a60567SRichard Henderson             goto done;
598b0a60567SRichard Henderson         }
599b0a60567SRichard Henderson     }
600b0a60567SRichard Henderson 
601b0a60567SRichard Henderson     mask = (1u << len) - 1;
602951c6300SRichard Henderson     if (ofs + len < 32) {
603951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
604951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
605951c6300SRichard Henderson     } else {
606951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
607951c6300SRichard Henderson     }
608951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
609951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
610b0a60567SRichard Henderson  done:
611951c6300SRichard Henderson     tcg_temp_free_i32(t1);
612951c6300SRichard Henderson }
613951c6300SRichard Henderson 
61407cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
61507cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
61607cc68d5SRichard Henderson {
61707cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
61807cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
61907cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
62007cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
62107cc68d5SRichard Henderson 
62207cc68d5SRichard Henderson     if (ofs + len == 32) {
62307cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
62407cc68d5SRichard Henderson     } else if (ofs == 0) {
62507cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
62607cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
62707cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
62811d11d61SRichard Henderson         TCGv_i32 zero = tcg_constant_i32(0);
62907cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
63007cc68d5SRichard Henderson     } else {
63107cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
63207cc68d5SRichard Henderson            which allows ARG to stay live.  */
63307cc68d5SRichard Henderson         switch (len) {
63407cc68d5SRichard Henderson         case 16:
63507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
63607cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
63707cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
63807cc68d5SRichard Henderson                 return;
63907cc68d5SRichard Henderson             }
64007cc68d5SRichard Henderson             break;
64107cc68d5SRichard Henderson         case 8:
64207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
64307cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
64407cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
64507cc68d5SRichard Henderson                 return;
64607cc68d5SRichard Henderson             }
64707cc68d5SRichard Henderson             break;
64807cc68d5SRichard Henderson         }
64907cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
65007cc68d5SRichard Henderson         switch (ofs + len) {
65107cc68d5SRichard Henderson         case 16:
65207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
65307cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
65407cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
65507cc68d5SRichard Henderson                 return;
65607cc68d5SRichard Henderson             }
65707cc68d5SRichard Henderson             break;
65807cc68d5SRichard Henderson         case 8:
65907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
66007cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
66107cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
66207cc68d5SRichard Henderson                 return;
66307cc68d5SRichard Henderson             }
66407cc68d5SRichard Henderson             break;
66507cc68d5SRichard Henderson         }
66607cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
66707cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
66807cc68d5SRichard Henderson     }
66907cc68d5SRichard Henderson }
67007cc68d5SRichard Henderson 
6717ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
6727ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
6737ec8bab3SRichard Henderson {
6747ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
6757ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
6767ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
6777ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
6787ec8bab3SRichard Henderson 
6797ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
6807ec8bab3SRichard Henderson     if (ofs + len == 32) {
6817ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
6827ec8bab3SRichard Henderson         return;
6837ec8bab3SRichard Henderson     }
6847ec8bab3SRichard Henderson     if (ofs == 0) {
6857ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
6867ec8bab3SRichard Henderson         return;
6877ec8bab3SRichard Henderson     }
6887ec8bab3SRichard Henderson 
6897ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
6907ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
6917ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
6927ec8bab3SRichard Henderson         return;
6937ec8bab3SRichard Henderson     }
6947ec8bab3SRichard Henderson 
6957ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
6967ec8bab3SRichard Henderson     switch (ofs + len) {
6977ec8bab3SRichard Henderson     case 16:
6987ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
6997ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7007ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7017ec8bab3SRichard Henderson             return;
7027ec8bab3SRichard Henderson         }
7037ec8bab3SRichard Henderson         break;
7047ec8bab3SRichard Henderson     case 8:
7057ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7067ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7077ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7087ec8bab3SRichard Henderson             return;
7097ec8bab3SRichard Henderson         }
7107ec8bab3SRichard Henderson         break;
7117ec8bab3SRichard Henderson     }
7127ec8bab3SRichard Henderson 
7137ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7147ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7157ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7167ec8bab3SRichard Henderson     switch (len) {
7177ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7187ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7197ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7207ec8bab3SRichard Henderson         break;
7217ec8bab3SRichard Henderson     default:
7227ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7237ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7247ec8bab3SRichard Henderson         break;
7257ec8bab3SRichard Henderson     }
7267ec8bab3SRichard Henderson }
7277ec8bab3SRichard Henderson 
7287ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7297ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7307ec8bab3SRichard Henderson {
7317ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7327ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7337ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7347ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7357ec8bab3SRichard Henderson 
7367ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7377ec8bab3SRichard Henderson     if (ofs + len == 32) {
7387ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7397ec8bab3SRichard Henderson         return;
7407ec8bab3SRichard Henderson     }
7417ec8bab3SRichard Henderson     if (ofs == 0) {
7427ec8bab3SRichard Henderson         switch (len) {
7437ec8bab3SRichard Henderson         case 16:
7447ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7457ec8bab3SRichard Henderson             return;
7467ec8bab3SRichard Henderson         case 8:
7477ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7487ec8bab3SRichard Henderson             return;
7497ec8bab3SRichard Henderson         }
7507ec8bab3SRichard Henderson     }
7517ec8bab3SRichard Henderson 
7527ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7537ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7547ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7557ec8bab3SRichard Henderson         return;
7567ec8bab3SRichard Henderson     }
7577ec8bab3SRichard Henderson 
7587ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7597ec8bab3SRichard Henderson     switch (ofs + len) {
7607ec8bab3SRichard Henderson     case 16:
7617ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7627ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7637ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7647ec8bab3SRichard Henderson             return;
7657ec8bab3SRichard Henderson         }
7667ec8bab3SRichard Henderson         break;
7677ec8bab3SRichard Henderson     case 8:
7687ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7697ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7707ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7717ec8bab3SRichard Henderson             return;
7727ec8bab3SRichard Henderson         }
7737ec8bab3SRichard Henderson         break;
7747ec8bab3SRichard Henderson     }
7757ec8bab3SRichard Henderson     switch (len) {
7767ec8bab3SRichard Henderson     case 16:
7777ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7787ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7797ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
7807ec8bab3SRichard Henderson             return;
7817ec8bab3SRichard Henderson         }
7827ec8bab3SRichard Henderson         break;
7837ec8bab3SRichard Henderson     case 8:
7847ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7857ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7867ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
7877ec8bab3SRichard Henderson             return;
7887ec8bab3SRichard Henderson         }
7897ec8bab3SRichard Henderson         break;
7907ec8bab3SRichard Henderson     }
7917ec8bab3SRichard Henderson 
7927ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7937ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
7947ec8bab3SRichard Henderson }
7957ec8bab3SRichard Henderson 
7962089fcc9SDavid Hildenbrand /*
7972089fcc9SDavid Hildenbrand  * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
7982089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
7992089fcc9SDavid Hildenbrand  */
8002089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
8012089fcc9SDavid Hildenbrand                           unsigned int ofs)
8022089fcc9SDavid Hildenbrand {
8032089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 32);
8042089fcc9SDavid Hildenbrand     if (ofs == 0) {
8052089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, al);
8062089fcc9SDavid Hildenbrand     } else if (ofs == 32) {
8072089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, ah);
8082089fcc9SDavid Hildenbrand     } else if (al == ah) {
8092089fcc9SDavid Hildenbrand         tcg_gen_rotri_i32(ret, al, ofs);
810fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i32) {
811fce1296fSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
8122089fcc9SDavid Hildenbrand     } else {
8132089fcc9SDavid Hildenbrand         TCGv_i32 t0 = tcg_temp_new_i32();
8142089fcc9SDavid Hildenbrand         tcg_gen_shri_i32(t0, al, ofs);
8152089fcc9SDavid Hildenbrand         tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs);
8162089fcc9SDavid Hildenbrand         tcg_temp_free_i32(t0);
8172089fcc9SDavid Hildenbrand     }
8182089fcc9SDavid Hildenbrand }
8192089fcc9SDavid Hildenbrand 
820951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
821951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
822951c6300SRichard Henderson {
82337ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
82437ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
82537ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
82637ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
82737ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
828951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
829951c6300SRichard Henderson     } else {
830951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
831951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
832951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
833951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
834951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
835951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
836951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
837951c6300SRichard Henderson         tcg_temp_free_i32(t0);
838951c6300SRichard Henderson         tcg_temp_free_i32(t1);
839951c6300SRichard Henderson     }
840951c6300SRichard Henderson }
841951c6300SRichard Henderson 
842951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
843951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
844951c6300SRichard Henderson {
845951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
846951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
847951c6300SRichard Henderson     } else {
848951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
849951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
850951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
851951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
852951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
853951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
854951c6300SRichard Henderson         tcg_temp_free_i64(t0);
855951c6300SRichard Henderson         tcg_temp_free_i64(t1);
856951c6300SRichard Henderson     }
857951c6300SRichard Henderson }
858951c6300SRichard Henderson 
859951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
860951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
861951c6300SRichard Henderson {
862951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
863951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
864951c6300SRichard Henderson     } else {
865951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
866951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
867951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
868951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
869951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
870951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
871951c6300SRichard Henderson         tcg_temp_free_i64(t0);
872951c6300SRichard Henderson         tcg_temp_free_i64(t1);
873951c6300SRichard Henderson     }
874951c6300SRichard Henderson }
875951c6300SRichard Henderson 
876951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
877951c6300SRichard Henderson {
878951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
879951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
880951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
881951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
882951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
883951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
884951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
885951c6300SRichard Henderson         tcg_temp_free_i32(t);
886951c6300SRichard Henderson     } else {
887951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
888951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
889951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
890951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
891951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
892951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
893951c6300SRichard Henderson         tcg_temp_free_i64(t0);
894951c6300SRichard Henderson         tcg_temp_free_i64(t1);
895951c6300SRichard Henderson     }
896951c6300SRichard Henderson }
897951c6300SRichard Henderson 
898951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
899951c6300SRichard Henderson {
900951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
901951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
902951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
903951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
904951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
905951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
906951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
907951c6300SRichard Henderson         tcg_temp_free_i32(t);
908951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
909951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
910951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
911951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
912951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
913951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
914951c6300SRichard Henderson         /* Adjust for negative inputs.  */
915951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
916951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
917951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
918951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
919951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
920951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
921951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
922951c6300SRichard Henderson         tcg_temp_free_i32(t0);
923951c6300SRichard Henderson         tcg_temp_free_i32(t1);
924951c6300SRichard Henderson         tcg_temp_free_i32(t2);
925951c6300SRichard Henderson         tcg_temp_free_i32(t3);
926951c6300SRichard Henderson     } else {
927951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
928951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
929951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
930951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
931951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
932951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
933951c6300SRichard Henderson         tcg_temp_free_i64(t0);
934951c6300SRichard Henderson         tcg_temp_free_i64(t1);
935951c6300SRichard Henderson     }
936951c6300SRichard Henderson }
937951c6300SRichard Henderson 
9385087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9395087abfbSRichard Henderson {
9405087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9415087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9425087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9435087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9445087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9455087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9465087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9475087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9485087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9495087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9505087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9515087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9525087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9535087abfbSRichard Henderson     } else {
9545087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9555087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9565087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9575087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9585087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9595087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9605087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9615087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9625087abfbSRichard Henderson     }
9635087abfbSRichard Henderson }
9645087abfbSRichard Henderson 
965951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
966951c6300SRichard Henderson {
967951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
968951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
969951c6300SRichard Henderson     } else {
970951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
971951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
972951c6300SRichard Henderson     }
973951c6300SRichard Henderson }
974951c6300SRichard Henderson 
975951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
976951c6300SRichard Henderson {
977951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
978951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
979951c6300SRichard Henderson     } else {
980951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
981951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
982951c6300SRichard Henderson     }
983951c6300SRichard Henderson }
984951c6300SRichard Henderson 
985951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
986951c6300SRichard Henderson {
987951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
988951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
989951c6300SRichard Henderson     } else {
990951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
991951c6300SRichard Henderson     }
992951c6300SRichard Henderson }
993951c6300SRichard Henderson 
994951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
995951c6300SRichard Henderson {
996951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
997951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
998951c6300SRichard Henderson     } else {
999951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1000951c6300SRichard Henderson     }
1001951c6300SRichard Henderson }
1002951c6300SRichard Henderson 
10032b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
1004951c6300SRichard Henderson {
10052b836c2aSRichard Henderson     /* Only one extension flag may be present. */
10062b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
10072b836c2aSRichard Henderson 
1008951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
10092b836c2aSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags);
1010951c6300SRichard Henderson     } else {
1011951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
10122b836c2aSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
1013951c6300SRichard Henderson 
10142b836c2aSRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);
10152b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
10162b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t0, t0);
10172b836c2aSRichard Henderson         }
10182b836c2aSRichard Henderson 
10192b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
10202b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 24);
10212b836c2aSRichard Henderson             tcg_gen_sari_i32(t1, t1, 16);
10222b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
10232b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t1, arg);
10242b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, t1, 8);
10252b836c2aSRichard Henderson         } else {
10262b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 8);
10272b836c2aSRichard Henderson         }
10282b836c2aSRichard Henderson 
10292b836c2aSRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1030951c6300SRichard Henderson         tcg_temp_free_i32(t0);
10312b836c2aSRichard Henderson         tcg_temp_free_i32(t1);
1032951c6300SRichard Henderson     }
1033951c6300SRichard Henderson }
1034951c6300SRichard Henderson 
1035951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1036951c6300SRichard Henderson {
1037951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1038587195bdSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
1039951c6300SRichard Henderson     } else {
1040a686dc71SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1041a686dc71SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
104211d11d61SRichard Henderson         TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
1043951c6300SRichard Henderson 
1044a686dc71SRichard Henderson                                         /* arg = abcd */
1045a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);   /*  t0 = .abc */
1046a686dc71SRichard Henderson         tcg_gen_and_i32(t1, arg, t2);   /*  t1 = .b.d */
1047a686dc71SRichard Henderson         tcg_gen_and_i32(t0, t0, t2);    /*  t0 = .a.c */
1048a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = b.d. */
1049a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = badc */
1050951c6300SRichard Henderson 
1051a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, ret, 16);  /*  t0 = ..ba */
1052a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, ret, 16);  /*  t1 = dc.. */
1053a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = dcba */
1054951c6300SRichard Henderson 
1055951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1056951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1057951c6300SRichard Henderson     }
1058951c6300SRichard Henderson }
1059951c6300SRichard Henderson 
1060b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1061b87fb8cdSRichard Henderson {
1062b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1063b87fb8cdSRichard Henderson }
1064b87fb8cdSRichard Henderson 
1065b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1066b87fb8cdSRichard Henderson {
1067b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1068b87fb8cdSRichard Henderson }
1069b87fb8cdSRichard Henderson 
1070b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1071b87fb8cdSRichard Henderson {
1072b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1073b87fb8cdSRichard Henderson }
1074b87fb8cdSRichard Henderson 
1075b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1076b87fb8cdSRichard Henderson {
1077b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1078b87fb8cdSRichard Henderson }
1079b87fb8cdSRichard Henderson 
1080ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
1081ff1f11f7SRichard Henderson {
1082ff1f11f7SRichard Henderson     TCGv_i32 t = tcg_temp_new_i32();
1083ff1f11f7SRichard Henderson 
1084ff1f11f7SRichard Henderson     tcg_gen_sari_i32(t, a, 31);
1085ff1f11f7SRichard Henderson     tcg_gen_xor_i32(ret, a, t);
1086ff1f11f7SRichard Henderson     tcg_gen_sub_i32(ret, ret, t);
1087ff1f11f7SRichard Henderson     tcg_temp_free_i32(t);
1088ff1f11f7SRichard Henderson }
1089ff1f11f7SRichard Henderson 
1090951c6300SRichard Henderson /* 64-bit ops */
1091951c6300SRichard Henderson 
1092951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1093951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1094951c6300SRichard Henderson 
1095951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1096951c6300SRichard Henderson {
1097951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1098951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1099951c6300SRichard Henderson }
1100951c6300SRichard Henderson 
1101951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1102951c6300SRichard Henderson {
110311d11d61SRichard Henderson     TCGTemp *ts = tcgv_i64_temp(arg);
110411d11d61SRichard Henderson 
110511d11d61SRichard Henderson     /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
110611d11d61SRichard Henderson     if (ts->kind == TEMP_CONST) {
110711d11d61SRichard Henderson         tcg_gen_movi_i64(ret, ts->val);
110811d11d61SRichard Henderson     } else {
1109951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1110951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1111951c6300SRichard Henderson     }
111211d11d61SRichard Henderson }
1113951c6300SRichard Henderson 
1114951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1115951c6300SRichard Henderson {
1116951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1117951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1118951c6300SRichard Henderson }
1119951c6300SRichard Henderson 
1120951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1121951c6300SRichard Henderson {
1122951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1123951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1124951c6300SRichard Henderson }
1125951c6300SRichard Henderson 
1126951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1127951c6300SRichard Henderson {
1128951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11293ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1130951c6300SRichard Henderson }
1131951c6300SRichard Henderson 
1132951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1133951c6300SRichard Henderson {
1134951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1135951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1136951c6300SRichard Henderson }
1137951c6300SRichard Henderson 
1138951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1139951c6300SRichard Henderson {
1140951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1141951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1142951c6300SRichard Henderson }
1143951c6300SRichard Henderson 
1144951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1145951c6300SRichard Henderson {
1146951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1147951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1148951c6300SRichard Henderson }
1149951c6300SRichard Henderson 
1150951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1151951c6300SRichard Henderson {
1152951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1153951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1154951c6300SRichard Henderson }
1155951c6300SRichard Henderson 
1156951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1157951c6300SRichard Henderson {
1158951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1159951c6300SRichard Henderson        they cannot be the same temporary */
1160cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1161951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1162951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1163951c6300SRichard Henderson #else
1164951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1165951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1166951c6300SRichard Henderson #endif
1167951c6300SRichard Henderson }
1168951c6300SRichard Henderson 
1169951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1170951c6300SRichard Henderson {
1171cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1172951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1173951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1174951c6300SRichard Henderson #else
1175951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1176951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1177951c6300SRichard Henderson #endif
1178951c6300SRichard Henderson }
1179951c6300SRichard Henderson 
1180951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1181951c6300SRichard Henderson {
1182951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1183951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1184951c6300SRichard Henderson }
1185951c6300SRichard Henderson 
1186951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1187951c6300SRichard Henderson {
1188951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1189951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1190951c6300SRichard Henderson }
1191951c6300SRichard Henderson 
1192951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1193951c6300SRichard Henderson {
1194951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1195951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1196951c6300SRichard Henderson }
1197951c6300SRichard Henderson 
1198951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1199951c6300SRichard Henderson {
1200951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1201951c6300SRichard Henderson }
1202951c6300SRichard Henderson 
1203951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1204951c6300SRichard Henderson {
1205951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1206951c6300SRichard Henderson }
1207951c6300SRichard Henderson 
1208951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1209951c6300SRichard Henderson {
1210951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1211951c6300SRichard Henderson }
1212951c6300SRichard Henderson 
1213951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1214951c6300SRichard Henderson {
1215951c6300SRichard Henderson     TCGv_i64 t0;
1216951c6300SRichard Henderson     TCGv_i32 t1;
1217951c6300SRichard Henderson 
1218951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1219951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1220951c6300SRichard Henderson 
1221951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1222951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1223951c6300SRichard Henderson 
1224951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1225951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1226951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1227951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1228951c6300SRichard Henderson 
1229951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1230951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1231951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1232951c6300SRichard Henderson }
123311d11d61SRichard Henderson 
123411d11d61SRichard Henderson #else
123511d11d61SRichard Henderson 
123611d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
123711d11d61SRichard Henderson {
123811d11d61SRichard Henderson     tcg_gen_mov_i64(ret, tcg_constant_i64(arg));
123911d11d61SRichard Henderson }
124011d11d61SRichard Henderson 
1241951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1242951c6300SRichard Henderson 
1243951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1244951c6300SRichard Henderson {
1245951c6300SRichard Henderson     /* some cases can be optimized here */
1246951c6300SRichard Henderson     if (arg2 == 0) {
1247951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
124811d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
124911d11d61SRichard Henderson         tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2));
1250951c6300SRichard Henderson     } else {
125111d11d61SRichard Henderson         tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
125211d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
125311d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1254951c6300SRichard Henderson     }
1255951c6300SRichard Henderson }
1256951c6300SRichard Henderson 
1257951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1258951c6300SRichard Henderson {
1259951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1260951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1261951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
126211d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
126311d11d61SRichard Henderson         tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
1264951c6300SRichard Henderson     } else {
126511d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
126611d11d61SRichard Henderson                          tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32),
126711d11d61SRichard Henderson                          TCGV_LOW(arg2), TCGV_HIGH(arg2));
1268951c6300SRichard Henderson     }
1269951c6300SRichard Henderson }
1270951c6300SRichard Henderson 
1271951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1272951c6300SRichard Henderson {
1273951c6300SRichard Henderson     /* some cases can be optimized here */
1274951c6300SRichard Henderson     if (arg2 == 0) {
1275951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
127611d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
127711d11d61SRichard Henderson         tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2));
1278951c6300SRichard Henderson     } else {
127911d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
128011d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
128111d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1282951c6300SRichard Henderson     }
1283951c6300SRichard Henderson }
1284951c6300SRichard Henderson 
1285474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1286951c6300SRichard Henderson {
12873a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1288951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1289951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12903a13c3f3SRichard Henderson         return;
12913a13c3f3SRichard Henderson     }
12923a13c3f3SRichard Henderson 
1293951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1294951c6300SRichard Henderson     switch (arg2) {
1295951c6300SRichard Henderson     case 0:
1296951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1297951c6300SRichard Henderson         return;
1298474b2e8fSRichard Henderson     case -1:
1299951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1300951c6300SRichard Henderson         return;
1301474b2e8fSRichard Henderson     case 0xff:
1302951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1303951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1304951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1305951c6300SRichard Henderson             return;
1306951c6300SRichard Henderson         }
1307951c6300SRichard Henderson         break;
1308474b2e8fSRichard Henderson     case 0xffff:
1309951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1310951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1311951c6300SRichard Henderson             return;
1312951c6300SRichard Henderson         }
1313951c6300SRichard Henderson         break;
1314474b2e8fSRichard Henderson     case 0xffffffffu:
1315951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1316951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1317951c6300SRichard Henderson             return;
1318951c6300SRichard Henderson         }
1319951c6300SRichard Henderson         break;
1320951c6300SRichard Henderson     }
132111d11d61SRichard Henderson 
132211d11d61SRichard Henderson     tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2));
1323951c6300SRichard Henderson }
1324951c6300SRichard Henderson 
1325951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1326951c6300SRichard Henderson {
13273a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1328951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1329951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13303a13c3f3SRichard Henderson         return;
13313a13c3f3SRichard Henderson     }
1332951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1333951c6300SRichard Henderson     if (arg2 == -1) {
1334951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1335951c6300SRichard Henderson     } else if (arg2 == 0) {
1336951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1337951c6300SRichard Henderson     } else {
133811d11d61SRichard Henderson         tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2));
1339951c6300SRichard Henderson     }
1340951c6300SRichard Henderson }
1341951c6300SRichard Henderson 
1342951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1343951c6300SRichard Henderson {
13443a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1345951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1346951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13473a13c3f3SRichard Henderson         return;
13483a13c3f3SRichard Henderson     }
1349951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1350951c6300SRichard Henderson     if (arg2 == 0) {
1351951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1352951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1353951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1354951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1355951c6300SRichard Henderson     } else {
135611d11d61SRichard Henderson         tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2));
1357951c6300SRichard Henderson     }
1358951c6300SRichard Henderson }
1359951c6300SRichard Henderson 
1360951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1361951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1362951c6300SRichard Henderson {
1363951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1364951c6300SRichard Henderson     if (c == 0) {
1365951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1366951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1367951c6300SRichard Henderson     } else if (c >= 32) {
1368951c6300SRichard Henderson         c -= 32;
1369951c6300SRichard Henderson         if (right) {
1370951c6300SRichard Henderson             if (arith) {
1371951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1372951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1373951c6300SRichard Henderson             } else {
1374951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1375951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1376951c6300SRichard Henderson             }
1377951c6300SRichard Henderson         } else {
1378951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1379951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1380951c6300SRichard Henderson         }
138102616badSRichard Henderson     } else if (right) {
138202616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
138302616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_LOW(ret),
138402616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1385951c6300SRichard Henderson         } else {
1386951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
138702616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret),
138802616badSRichard Henderson                                 TCGV_HIGH(arg1), 32 - c, c);
1389951c6300SRichard Henderson         }
139002616badSRichard Henderson         if (arith) {
139102616badSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
139202616badSRichard Henderson         } else {
139302616badSRichard Henderson             tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
139402616badSRichard Henderson         }
139502616badSRichard Henderson     } else {
139602616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
139702616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_HIGH(ret),
139802616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
139902616badSRichard Henderson         } else {
140002616badSRichard Henderson             TCGv_i32 t0 = tcg_temp_new_i32();
140102616badSRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
140202616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), t0,
140302616badSRichard Henderson                                 TCGV_HIGH(arg1), c, 32 - c);
1404951c6300SRichard Henderson             tcg_temp_free_i32(t0);
140502616badSRichard Henderson         }
140602616badSRichard Henderson         tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1407951c6300SRichard Henderson     }
1408951c6300SRichard Henderson }
1409951c6300SRichard Henderson 
1410474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1411951c6300SRichard Henderson {
1412474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14143a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
14153a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1416951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1417951c6300SRichard Henderson     } else {
141811d11d61SRichard Henderson         tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2));
1419951c6300SRichard Henderson     }
1420951c6300SRichard Henderson }
1421951c6300SRichard Henderson 
1422474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1423951c6300SRichard Henderson {
1424474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14263a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
14273a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1428951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1429951c6300SRichard Henderson     } else {
143011d11d61SRichard Henderson         tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2));
1431951c6300SRichard Henderson     }
1432951c6300SRichard Henderson }
1433951c6300SRichard Henderson 
1434474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1435951c6300SRichard Henderson {
1436474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14373a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14383a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
14393a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1440951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1441951c6300SRichard Henderson     } else {
144211d11d61SRichard Henderson         tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2));
1443951c6300SRichard Henderson     }
1444951c6300SRichard Henderson }
1445951c6300SRichard Henderson 
144642a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1447951c6300SRichard Henderson {
1448951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
144942a268c2SRichard Henderson         tcg_gen_br(l);
1450951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1451d88a117eSRichard Henderson         l->refs++;
14523a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1453951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1454951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
145542a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14563a13c3f3SRichard Henderson         } else {
145742a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
145842a268c2SRichard Henderson                               label_arg(l));
14593a13c3f3SRichard Henderson         }
1460951c6300SRichard Henderson     }
1461951c6300SRichard Henderson }
1462951c6300SRichard Henderson 
146342a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1464951c6300SRichard Henderson {
146511d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
146611d11d61SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l);
146711d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
146842a268c2SRichard Henderson         tcg_gen_br(l);
1469951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
147011d11d61SRichard Henderson         l->refs++;
147111d11d61SRichard Henderson         tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
147211d11d61SRichard Henderson                           TCGV_LOW(arg1), TCGV_HIGH(arg1),
147311d11d61SRichard Henderson                           tcg_constant_i32(arg2),
147411d11d61SRichard Henderson                           tcg_constant_i32(arg2 >> 32),
147511d11d61SRichard Henderson                           cond, label_arg(l));
1476951c6300SRichard Henderson     }
1477951c6300SRichard Henderson }
1478951c6300SRichard Henderson 
1479951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1480951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1481951c6300SRichard Henderson {
1482951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1483951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1484951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1485951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1486951c6300SRichard Henderson     } else {
14873a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1488951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1489951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1490951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1491951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
14923a13c3f3SRichard Henderson         } else {
1493951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
14943a13c3f3SRichard Henderson         }
1495951c6300SRichard Henderson     }
1496951c6300SRichard Henderson }
1497951c6300SRichard Henderson 
1498951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1499951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1500951c6300SRichard Henderson {
150111d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
150211d11d61SRichard Henderson         tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2));
150311d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
150411d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 1);
150511d11d61SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
150611d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 0);
150711d11d61SRichard Henderson     } else {
150811d11d61SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
150911d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
151011d11d61SRichard Henderson                          tcg_constant_i32(arg2),
151111d11d61SRichard Henderson                          tcg_constant_i32(arg2 >> 32), cond);
151211d11d61SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
151311d11d61SRichard Henderson     }
1514951c6300SRichard Henderson }
1515951c6300SRichard Henderson 
1516951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1517951c6300SRichard Henderson {
1518b2e3ae94SRichard Henderson     if (arg2 == 0) {
1519b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1520b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1521b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1522b2e3ae94SRichard Henderson     } else {
1523951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1524951c6300SRichard Henderson         tcg_gen_mul_i64(ret, arg1, t0);
1525951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1526951c6300SRichard Henderson     }
1527b2e3ae94SRichard Henderson }
1528951c6300SRichard Henderson 
1529951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1530951c6300SRichard Henderson {
1531951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1532951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1533951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1534951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1535951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1536951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1537951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1538951c6300SRichard Henderson     } else {
1539951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1540951c6300SRichard Henderson     }
1541951c6300SRichard Henderson }
1542951c6300SRichard Henderson 
1543951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1544951c6300SRichard Henderson {
1545951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1546951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1547951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1548951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1549951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1550951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1551951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1552951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1553951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1554951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1555951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1556951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1557951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1558951c6300SRichard Henderson     } else {
1559951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1560951c6300SRichard Henderson     }
1561951c6300SRichard Henderson }
1562951c6300SRichard Henderson 
1563951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1564951c6300SRichard Henderson {
1565951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1566951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1567951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1568951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1569951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1570951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1571951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1572951c6300SRichard Henderson     } else {
1573951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1574951c6300SRichard Henderson     }
1575951c6300SRichard Henderson }
1576951c6300SRichard Henderson 
1577951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1578951c6300SRichard Henderson {
1579951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1580951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1581951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1582951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1583951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1584951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1585951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1586951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1587951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1588951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1589951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1590951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1591951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1592951c6300SRichard Henderson     } else {
1593951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1594951c6300SRichard Henderson     }
1595951c6300SRichard Henderson }
1596951c6300SRichard Henderson 
1597951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1598951c6300SRichard Henderson {
15993a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1600951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1601951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16023a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1603951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1604951c6300SRichard Henderson     } else {
1605951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1606951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1607951c6300SRichard Henderson     }
1608951c6300SRichard Henderson }
1609951c6300SRichard Henderson 
1610951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1611951c6300SRichard Henderson {
16123a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1613951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1614951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16153a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1616951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1617951c6300SRichard Henderson     } else {
1618951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1619951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1620951c6300SRichard Henderson     }
1621951c6300SRichard Henderson }
1622951c6300SRichard Henderson 
1623951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1624951c6300SRichard Henderson {
16253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1626951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1627951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16283a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1629951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1630951c6300SRichard Henderson     } else {
1631951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1632951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1633951c6300SRichard Henderson     }
1634951c6300SRichard Henderson }
1635951c6300SRichard Henderson 
1636951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1637951c6300SRichard Henderson {
16383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1639951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1640951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16413a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1642951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1643951c6300SRichard Henderson     } else {
1644951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1645951c6300SRichard Henderson     }
1646951c6300SRichard Henderson }
1647951c6300SRichard Henderson 
1648951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1649951c6300SRichard Henderson {
16503a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1651951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1652951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16533a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1654951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1655951c6300SRichard Henderson     } else {
1656951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1657951c6300SRichard Henderson     }
1658951c6300SRichard Henderson }
1659951c6300SRichard Henderson 
1660951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1661951c6300SRichard Henderson {
16623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1663951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1664951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16653a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1666951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1667951c6300SRichard Henderson     } else {
1668951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1669951c6300SRichard Henderson     }
1670951c6300SRichard Henderson }
1671951c6300SRichard Henderson 
16722b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1673951c6300SRichard Henderson {
16742b836c2aSRichard Henderson     /* Only one extension flag may be present. */
16752b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
16762b836c2aSRichard Henderson 
16773a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
16782b836c2aSRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags);
16792b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
16802b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16812b836c2aSRichard Henderson         } else {
1682951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16832b836c2aSRichard Henderson         }
16843a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
16852b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags);
1686951c6300SRichard Henderson     } else {
1687951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
16882b836c2aSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1689951c6300SRichard Henderson 
16902b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);
16912b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
16922b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t0, t0);
16932b836c2aSRichard Henderson         }
16942b836c2aSRichard Henderson 
16952b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
16962b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 56);
16972b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 48);
16982b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
16992b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t1, arg);
17002b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, t1, 8);
17012b836c2aSRichard Henderson         } else {
17022b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 8);
17032b836c2aSRichard Henderson         }
17042b836c2aSRichard Henderson 
17052b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1706951c6300SRichard Henderson         tcg_temp_free_i64(t0);
17072b836c2aSRichard Henderson         tcg_temp_free_i64(t1);
1708951c6300SRichard Henderson     }
1709951c6300SRichard Henderson }
1710951c6300SRichard Henderson 
17112b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1712951c6300SRichard Henderson {
17132b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17142b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17152b836c2aSRichard Henderson 
17163a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1717951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17182b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17192b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17202b836c2aSRichard Henderson         } else {
1721951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17222b836c2aSRichard Henderson         }
17233a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
17242b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags);
1725951c6300SRichard Henderson     } else {
1726a686dc71SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1727a686dc71SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
172811d11d61SRichard Henderson         TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
1729951c6300SRichard Henderson 
17302b836c2aSRichard Henderson                                             /* arg = xxxxabcd */
17312b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);       /*  t0 = .xxxxabc */
1732a686dc71SRichard Henderson         tcg_gen_and_i64(t1, arg, t2);       /*  t1 = .....b.d */
1733a686dc71SRichard Henderson         tcg_gen_and_i64(t0, t0, t2);        /*  t0 = .....a.c */
1734a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);        /*  t1 = ....b.d. */
1735a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ....badc */
1736951c6300SRichard Henderson 
1737a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, ret, 48);      /*  t1 = dc...... */
1738a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);      /*  t0 = ......ba */
17392b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17402b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 32);   /*  t1 = ssssdc.. */
17412b836c2aSRichard Henderson         } else {
1742a686dc71SRichard Henderson             tcg_gen_shri_i64(t1, t1, 32);   /*  t1 = ....dc.. */
17432b836c2aSRichard Henderson         }
17442b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ssssdcba */
1745951c6300SRichard Henderson 
1746951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1747951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1748951c6300SRichard Henderson     }
1749951c6300SRichard Henderson }
1750951c6300SRichard Henderson 
1751951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1752951c6300SRichard Henderson {
17533a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1754951c6300SRichard Henderson         TCGv_i32 t0, t1;
1755951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1756951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1757951c6300SRichard Henderson 
1758951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1759951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1760951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1761951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1762951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1763951c6300SRichard Henderson         tcg_temp_free_i32(t1);
17643a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1765587195bdSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
1766951c6300SRichard Henderson     } else {
1767951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1768951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
17699e821eabSRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
1770951c6300SRichard Henderson 
17719e821eabSRichard Henderson                                         /* arg = abcdefgh */
17729e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
17739e821eabSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .abcdefg */
17749e821eabSRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .b.d.f.h */
17759e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .a.c.e.g */
17769e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = b.d.f.h. */
17779e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = badcfehg */
1778951c6300SRichard Henderson 
17799e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
17809e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ..badcfe */
17819e821eabSRichard Henderson         tcg_gen_and_i64(t1, ret, t2);   /*  t1 = ..dc..hg */
17829e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = ..ba..fe */
17839e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 16);   /*  t1 = dc..hg.. */
17849e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = dcbahgfe */
1785951c6300SRichard Henderson 
17869e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 32);  /*  t0 = ....dcba */
17879e821eabSRichard Henderson         tcg_gen_shli_i64(t1, ret, 32);  /*  t1 = hgfe.... */
17889e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = hgfedcba */
1789951c6300SRichard Henderson 
1790951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1791951c6300SRichard Henderson         tcg_temp_free_i64(t1);
17929e821eabSRichard Henderson         tcg_temp_free_i64(t2);
1793951c6300SRichard Henderson     }
1794951c6300SRichard Henderson }
1795951c6300SRichard Henderson 
1796951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1797951c6300SRichard Henderson {
17983a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17993a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
18003a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
18013a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1802951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1803951c6300SRichard Henderson     } else {
1804951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1805951c6300SRichard Henderson     }
1806951c6300SRichard Henderson }
1807951c6300SRichard Henderson 
1808951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1809951c6300SRichard Henderson {
18103a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18113a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18123a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18133a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1814951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1815951c6300SRichard Henderson     } else {
1816951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1817951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1818951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1819951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1820951c6300SRichard Henderson     }
1821951c6300SRichard Henderson }
1822951c6300SRichard Henderson 
1823951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1824951c6300SRichard Henderson {
18253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18263a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18273a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18283a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1829951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1830951c6300SRichard Henderson     } else {
1831951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1832951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1833951c6300SRichard Henderson     }
1834951c6300SRichard Henderson }
1835951c6300SRichard Henderson 
1836951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1837951c6300SRichard Henderson {
18383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18393a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18403a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18413a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1842951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1843951c6300SRichard Henderson     } else {
1844951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1845951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1846951c6300SRichard Henderson     }
1847951c6300SRichard Henderson }
1848951c6300SRichard Henderson 
1849951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1850951c6300SRichard Henderson {
18513a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18523a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18533a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1855951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1856951c6300SRichard Henderson     } else {
1857951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1858951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1859951c6300SRichard Henderson     }
1860951c6300SRichard Henderson }
1861951c6300SRichard Henderson 
1862951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1863951c6300SRichard Henderson {
18643a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18653a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18663a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18673a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1868951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1869951c6300SRichard Henderson     } else {
1870951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1871951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1872951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1873951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1874951c6300SRichard Henderson     }
1875951c6300SRichard Henderson }
1876951c6300SRichard Henderson 
18770e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18780e28d006SRichard Henderson {
18790e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
18800e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
18810e28d006SRichard Henderson     } else {
18820e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
18830e28d006SRichard Henderson     }
18840e28d006SRichard Henderson }
18850e28d006SRichard Henderson 
18860e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18870e28d006SRichard Henderson {
18880e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18890e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
18900e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
189111d11d61SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
189211d11d61SRichard Henderson         tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32);
18930e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
18940e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
18950e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18960e28d006SRichard Henderson         tcg_temp_free_i32(t);
18970e28d006SRichard Henderson     } else {
189811d11d61SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
189911d11d61SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t0);
190011d11d61SRichard Henderson         tcg_temp_free_i64(t0);
19010e28d006SRichard Henderson     }
19020e28d006SRichard Henderson }
19030e28d006SRichard Henderson 
19040e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
19050e28d006SRichard Henderson {
19060e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
19070e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
190814e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
190914e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
191014e99210SRichard Henderson 
191114e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
191214e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
191314e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
191414e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
191514e99210SRichard Henderson         } else {
191614e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
191714e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
191814e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
191914e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
192014e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
192114e99210SRichard Henderson         }
192211d11d61SRichard Henderson         z = tcg_constant_i64(0);
192314e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
192414e99210SRichard Henderson         tcg_temp_free_i64(t);
192514e99210SRichard Henderson         tcg_temp_free_i64(z);
19260e28d006SRichard Henderson     } else {
19270e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
19280e28d006SRichard Henderson     }
19290e28d006SRichard Henderson }
19300e28d006SRichard Henderson 
19310e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
19320e28d006SRichard Henderson {
19330e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
19340e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
19350e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
193611d11d61SRichard Henderson         TCGv_i32 t32 = tcg_temp_new_i32();
193711d11d61SRichard Henderson         tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32);
19380e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
19390e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
19400e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
19410e28d006SRichard Henderson         tcg_temp_free_i32(t32);
194214e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
194314e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
194414e99210SRichard Henderson                && arg2 == 64) {
194514e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
194614e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
194714e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
194814e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
194914e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
195014e99210SRichard Henderson         tcg_temp_free_i64(t);
19510e28d006SRichard Henderson     } else {
195211d11d61SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
195311d11d61SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t0);
195411d11d61SRichard Henderson         tcg_temp_free_i64(t0);
19550e28d006SRichard Henderson     }
19560e28d006SRichard Henderson }
19570e28d006SRichard Henderson 
1958086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
1959086920c2SRichard Henderson {
1960086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
1961086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1962086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
1963086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
1964086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
1965086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
1966086920c2SRichard Henderson         tcg_temp_free_i64(t);
1967086920c2SRichard Henderson     } else {
1968086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
1969086920c2SRichard Henderson     }
1970086920c2SRichard Henderson }
1971086920c2SRichard Henderson 
1972a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
1973a768e4e9SRichard Henderson {
1974a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
1975a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
1976a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
1977a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1978a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1979a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
1980a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1981a768e4e9SRichard Henderson     } else {
1982a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
1983a768e4e9SRichard Henderson     }
1984a768e4e9SRichard Henderson }
1985a768e4e9SRichard Henderson 
1986951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1987951c6300SRichard Henderson {
1988951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1989951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1990951c6300SRichard Henderson     } else {
1991951c6300SRichard Henderson         TCGv_i64 t0, t1;
1992951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1993951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1994951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1995951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1996951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1997951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1998951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1999951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2000951c6300SRichard Henderson     }
2001951c6300SRichard Henderson }
2002951c6300SRichard Henderson 
200307dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2004951c6300SRichard Henderson {
200507dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2006951c6300SRichard Henderson     /* some cases can be optimized here */
2007951c6300SRichard Henderson     if (arg2 == 0) {
2008951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2009951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
201011d11d61SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2));
2011951c6300SRichard Henderson     } else {
2012951c6300SRichard Henderson         TCGv_i64 t0, t1;
2013951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2014951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2015951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
2016951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
2017951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2018951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2019951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2020951c6300SRichard Henderson     }
2021951c6300SRichard Henderson }
2022951c6300SRichard Henderson 
2023951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2024951c6300SRichard Henderson {
2025951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2026951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
2027951c6300SRichard Henderson     } else {
2028951c6300SRichard Henderson         TCGv_i64 t0, t1;
2029951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2030951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2031951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
2032951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2033951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
2034951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2035951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2036951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2037951c6300SRichard Henderson     }
2038951c6300SRichard Henderson }
2039951c6300SRichard Henderson 
204007dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2041951c6300SRichard Henderson {
204207dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2043951c6300SRichard Henderson     /* some cases can be optimized here */
2044951c6300SRichard Henderson     if (arg2 == 0) {
2045951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2046951c6300SRichard Henderson     } else {
2047951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
2048951c6300SRichard Henderson     }
2049951c6300SRichard Henderson }
2050951c6300SRichard Henderson 
2051951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
2052951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
2053951c6300SRichard Henderson {
2054951c6300SRichard Henderson     uint64_t mask;
2055951c6300SRichard Henderson     TCGv_i64 t1;
2056951c6300SRichard Henderson 
2057951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
20580d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2059951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2060951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2061951c6300SRichard Henderson 
20620d0d309dSRichard Henderson     if (len == 64) {
2063951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2064951c6300SRichard Henderson         return;
2065951c6300SRichard Henderson     }
2066951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2067951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2068951c6300SRichard Henderson         return;
2069951c6300SRichard Henderson     }
2070951c6300SRichard Henderson 
20713a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2072951c6300SRichard Henderson         if (ofs >= 32) {
2073951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2074951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2075951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2076951c6300SRichard Henderson             return;
2077951c6300SRichard Henderson         }
2078951c6300SRichard Henderson         if (ofs + len <= 32) {
2079951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2080951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2081951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2082951c6300SRichard Henderson             return;
2083951c6300SRichard Henderson         }
20843a13c3f3SRichard Henderson     }
2085951c6300SRichard Henderson 
2086951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2087951c6300SRichard Henderson 
2088b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i64) {
2089b0a60567SRichard Henderson         if (ofs + len == 64) {
2090b0a60567SRichard Henderson             tcg_gen_shli_i64(t1, arg1, len);
2091b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, t1, arg2, len);
2092b0a60567SRichard Henderson             goto done;
2093b0a60567SRichard Henderson         }
2094b0a60567SRichard Henderson         if (ofs == 0) {
2095b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, arg1, arg2, len);
2096b0a60567SRichard Henderson             tcg_gen_rotli_i64(ret, ret, len);
2097b0a60567SRichard Henderson             goto done;
2098b0a60567SRichard Henderson         }
2099b0a60567SRichard Henderson     }
2100b0a60567SRichard Henderson 
2101b0a60567SRichard Henderson     mask = (1ull << len) - 1;
2102951c6300SRichard Henderson     if (ofs + len < 64) {
2103951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2104951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2105951c6300SRichard Henderson     } else {
2106951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2107951c6300SRichard Henderson     }
2108951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2109951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2110b0a60567SRichard Henderson  done:
2111951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2112951c6300SRichard Henderson }
2113951c6300SRichard Henderson 
211407cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
211507cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
211607cc68d5SRichard Henderson {
211707cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
211807cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
211907cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
212007cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
212107cc68d5SRichard Henderson 
212207cc68d5SRichard Henderson     if (ofs + len == 64) {
212307cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
212407cc68d5SRichard Henderson     } else if (ofs == 0) {
212507cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
212607cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
212707cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
212811d11d61SRichard Henderson         TCGv_i64 zero = tcg_constant_i64(0);
212907cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
213007cc68d5SRichard Henderson     } else {
213107cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
213207cc68d5SRichard Henderson             if (ofs >= 32) {
213307cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
213407cc68d5SRichard Henderson                                       ofs - 32, len);
213507cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
213607cc68d5SRichard Henderson                 return;
213707cc68d5SRichard Henderson             }
213807cc68d5SRichard Henderson             if (ofs + len <= 32) {
213907cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
214007cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
214107cc68d5SRichard Henderson                 return;
214207cc68d5SRichard Henderson             }
214307cc68d5SRichard Henderson         }
214407cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
214507cc68d5SRichard Henderson            which allows ARG to stay live.  */
214607cc68d5SRichard Henderson         switch (len) {
214707cc68d5SRichard Henderson         case 32:
214807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
214907cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
215007cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
215107cc68d5SRichard Henderson                 return;
215207cc68d5SRichard Henderson             }
215307cc68d5SRichard Henderson             break;
215407cc68d5SRichard Henderson         case 16:
215507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
215607cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
215707cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
215807cc68d5SRichard Henderson                 return;
215907cc68d5SRichard Henderson             }
216007cc68d5SRichard Henderson             break;
216107cc68d5SRichard Henderson         case 8:
216207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
216307cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
216407cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
216507cc68d5SRichard Henderson                 return;
216607cc68d5SRichard Henderson             }
216707cc68d5SRichard Henderson             break;
216807cc68d5SRichard Henderson         }
216907cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
217007cc68d5SRichard Henderson         switch (ofs + len) {
217107cc68d5SRichard Henderson         case 32:
217207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
217307cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
217407cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
217507cc68d5SRichard Henderson                 return;
217607cc68d5SRichard Henderson             }
217707cc68d5SRichard Henderson             break;
217807cc68d5SRichard Henderson         case 16:
217907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
218007cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
218107cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
218207cc68d5SRichard Henderson                 return;
218307cc68d5SRichard Henderson             }
218407cc68d5SRichard Henderson             break;
218507cc68d5SRichard Henderson         case 8:
218607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
218707cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
218807cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
218907cc68d5SRichard Henderson                 return;
219007cc68d5SRichard Henderson             }
219107cc68d5SRichard Henderson             break;
219207cc68d5SRichard Henderson         }
219307cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
219407cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
219507cc68d5SRichard Henderson     }
219607cc68d5SRichard Henderson }
219707cc68d5SRichard Henderson 
21987ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
21997ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
22007ec8bab3SRichard Henderson {
22017ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22027ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22037ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22047ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22057ec8bab3SRichard Henderson 
22067ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
22077ec8bab3SRichard Henderson     if (ofs + len == 64) {
22087ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
22097ec8bab3SRichard Henderson         return;
22107ec8bab3SRichard Henderson     }
22117ec8bab3SRichard Henderson     if (ofs == 0) {
22127ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
22137ec8bab3SRichard Henderson         return;
22147ec8bab3SRichard Henderson     }
22157ec8bab3SRichard Henderson 
22167ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22177ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22187ec8bab3SRichard Henderson         if (ofs >= 32) {
22197ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22207ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22217ec8bab3SRichard Henderson             return;
22227ec8bab3SRichard Henderson         }
22237ec8bab3SRichard Henderson         if (ofs + len <= 32) {
22247ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22257ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22267ec8bab3SRichard Henderson             return;
22277ec8bab3SRichard Henderson         }
22287ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
22297ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
22307ec8bab3SRichard Henderson         goto do_shift_and;
22317ec8bab3SRichard Henderson     }
22327ec8bab3SRichard Henderson 
22337ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
22347ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22357ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
22367ec8bab3SRichard Henderson         return;
22377ec8bab3SRichard Henderson     }
22387ec8bab3SRichard Henderson 
22397ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
22407ec8bab3SRichard Henderson     switch (ofs + len) {
22417ec8bab3SRichard Henderson     case 32:
22427ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
22437ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
22447ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22457ec8bab3SRichard Henderson             return;
22467ec8bab3SRichard Henderson         }
22477ec8bab3SRichard Henderson         break;
22487ec8bab3SRichard Henderson     case 16:
22497ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
22507ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
22517ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22527ec8bab3SRichard Henderson             return;
22537ec8bab3SRichard Henderson         }
22547ec8bab3SRichard Henderson         break;
22557ec8bab3SRichard Henderson     case 8:
22567ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
22577ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
22587ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22597ec8bab3SRichard Henderson             return;
22607ec8bab3SRichard Henderson         }
22617ec8bab3SRichard Henderson         break;
22627ec8bab3SRichard Henderson     }
22637ec8bab3SRichard Henderson 
22647ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
22657ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
22667ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
22677ec8bab3SRichard Henderson     switch (len) {
22687ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
22697ec8bab3SRichard Henderson     do_shift_and:
22707ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
22717ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
22727ec8bab3SRichard Henderson         break;
22737ec8bab3SRichard Henderson     default:
22747ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
22757ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
22767ec8bab3SRichard Henderson         break;
22777ec8bab3SRichard Henderson     }
22787ec8bab3SRichard Henderson }
22797ec8bab3SRichard Henderson 
22807ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
22817ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
22827ec8bab3SRichard Henderson {
22837ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22847ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22857ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22867ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22877ec8bab3SRichard Henderson 
22887ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
22897ec8bab3SRichard Henderson     if (ofs + len == 64) {
22907ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
22917ec8bab3SRichard Henderson         return;
22927ec8bab3SRichard Henderson     }
22937ec8bab3SRichard Henderson     if (ofs == 0) {
22947ec8bab3SRichard Henderson         switch (len) {
22957ec8bab3SRichard Henderson         case 32:
22967ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22977ec8bab3SRichard Henderson             return;
22987ec8bab3SRichard Henderson         case 16:
22997ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23007ec8bab3SRichard Henderson             return;
23017ec8bab3SRichard Henderson         case 8:
23027ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23037ec8bab3SRichard Henderson             return;
23047ec8bab3SRichard Henderson         }
23057ec8bab3SRichard Henderson     }
23067ec8bab3SRichard Henderson 
23077ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
23087ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
23097ec8bab3SRichard Henderson         if (ofs >= 32) {
23107ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
23117ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
23127ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
23137ec8bab3SRichard Henderson         } else if (ofs == 0) {
23147ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
23157ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
23167ec8bab3SRichard Henderson             return;
23177ec8bab3SRichard Henderson         } else if (len > 32) {
23187ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
23197ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
23207ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
23217ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
23227ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23237ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
23247ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
23257ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
23267ec8bab3SRichard Henderson             return;
23277ec8bab3SRichard Henderson         } else {
23287ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
23297ec8bab3SRichard Henderson                field sits at the MSB.  */
23307ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
23317ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
23327ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
23337ec8bab3SRichard Henderson         }
23347ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
23357ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
23367ec8bab3SRichard Henderson         return;
23377ec8bab3SRichard Henderson     }
23387ec8bab3SRichard Henderson 
23397ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
23407ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
23417ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
23427ec8bab3SRichard Henderson         return;
23437ec8bab3SRichard Henderson     }
23447ec8bab3SRichard Henderson 
23457ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
23467ec8bab3SRichard Henderson     switch (ofs + len) {
23477ec8bab3SRichard Henderson     case 32:
23487ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23497ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
23507ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23517ec8bab3SRichard Henderson             return;
23527ec8bab3SRichard Henderson         }
23537ec8bab3SRichard Henderson         break;
23547ec8bab3SRichard Henderson     case 16:
23557ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23567ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23577ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23587ec8bab3SRichard Henderson             return;
23597ec8bab3SRichard Henderson         }
23607ec8bab3SRichard Henderson         break;
23617ec8bab3SRichard Henderson     case 8:
23627ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23637ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23647ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23657ec8bab3SRichard Henderson             return;
23667ec8bab3SRichard Henderson         }
23677ec8bab3SRichard Henderson         break;
23687ec8bab3SRichard Henderson     }
23697ec8bab3SRichard Henderson     switch (len) {
23707ec8bab3SRichard Henderson     case 32:
23717ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23727ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23737ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
23747ec8bab3SRichard Henderson             return;
23757ec8bab3SRichard Henderson         }
23767ec8bab3SRichard Henderson         break;
23777ec8bab3SRichard Henderson     case 16:
23787ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23797ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23807ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
23817ec8bab3SRichard Henderson             return;
23827ec8bab3SRichard Henderson         }
23837ec8bab3SRichard Henderson         break;
23847ec8bab3SRichard Henderson     case 8:
23857ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23867ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23877ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
23887ec8bab3SRichard Henderson             return;
23897ec8bab3SRichard Henderson         }
23907ec8bab3SRichard Henderson         break;
23917ec8bab3SRichard Henderson     }
23927ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23937ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
23947ec8bab3SRichard Henderson }
23957ec8bab3SRichard Henderson 
23962089fcc9SDavid Hildenbrand /*
23972089fcc9SDavid Hildenbrand  * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
23982089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
23992089fcc9SDavid Hildenbrand  */
24002089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
24012089fcc9SDavid Hildenbrand                           unsigned int ofs)
24022089fcc9SDavid Hildenbrand {
24032089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 64);
24042089fcc9SDavid Hildenbrand     if (ofs == 0) {
24052089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, al);
24062089fcc9SDavid Hildenbrand     } else if (ofs == 64) {
24072089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, ah);
24082089fcc9SDavid Hildenbrand     } else if (al == ah) {
24092089fcc9SDavid Hildenbrand         tcg_gen_rotri_i64(ret, al, ofs);
2410fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i64) {
2411fce1296fSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
24122089fcc9SDavid Hildenbrand     } else {
24132089fcc9SDavid Hildenbrand         TCGv_i64 t0 = tcg_temp_new_i64();
24142089fcc9SDavid Hildenbrand         tcg_gen_shri_i64(t0, al, ofs);
24152089fcc9SDavid Hildenbrand         tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs);
24162089fcc9SDavid Hildenbrand         tcg_temp_free_i64(t0);
24172089fcc9SDavid Hildenbrand     }
24182089fcc9SDavid Hildenbrand }
24192089fcc9SDavid Hildenbrand 
2420951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2421951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2422951c6300SRichard Henderson {
242337ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
242437ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
242537ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
242637ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
242737ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2428951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2429951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2430951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2431951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2432951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2433951c6300SRichard Henderson 
2434951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2435951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2436951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2437951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2438951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2439951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2440951c6300SRichard Henderson         } else {
2441951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2442951c6300SRichard Henderson 
2443951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2444951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2445951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2446951c6300SRichard Henderson 
2447951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2448951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2449951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2450951c6300SRichard Henderson         }
2451951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2452951c6300SRichard Henderson         tcg_temp_free_i32(t1);
24533a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2454951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2455951c6300SRichard Henderson     } else {
2456951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2457951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2458951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2459951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2460951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2461951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2462951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2463951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2464951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2465951c6300SRichard Henderson     }
2466951c6300SRichard Henderson }
2467951c6300SRichard Henderson 
2468951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2469951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2470951c6300SRichard Henderson {
2471951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2472951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2473951c6300SRichard Henderson     } else {
2474951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2475951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2476951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2477951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2478951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2479951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2480951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2481951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2482951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2483951c6300SRichard Henderson     }
2484951c6300SRichard Henderson }
2485951c6300SRichard Henderson 
2486951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2487951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2488951c6300SRichard Henderson {
2489951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2490951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2491951c6300SRichard Henderson     } else {
2492951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2493951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2494951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2495951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2496951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2497951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2498951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2499951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2500951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2501951c6300SRichard Henderson     }
2502951c6300SRichard Henderson }
2503951c6300SRichard Henderson 
2504951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2505951c6300SRichard Henderson {
2506951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2507951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2508951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2509951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2510951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2511951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2512951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2513951c6300SRichard Henderson         tcg_temp_free_i64(t);
2514951c6300SRichard Henderson     } else {
2515951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2516951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2517951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2518951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2519951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2520951c6300SRichard Henderson     }
2521951c6300SRichard Henderson }
2522951c6300SRichard Henderson 
2523951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2524951c6300SRichard Henderson {
2525951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2526951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2527951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2528951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2529951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2530951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2531951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2532951c6300SRichard Henderson         tcg_temp_free_i64(t);
2533951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2534951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2535951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2536951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2537951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2538951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2539951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2540951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2541951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2542951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2543951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2544951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2545951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2546951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2547951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2548951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2549951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2550951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2551951c6300SRichard Henderson     } else {
2552951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2553951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2554951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2555951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2556951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2557951c6300SRichard Henderson     }
2558951c6300SRichard Henderson }
2559951c6300SRichard Henderson 
25605087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
25615087abfbSRichard Henderson {
25625087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
25635087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
25645087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
25655087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
25665087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
25675087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
25685087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
25695087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
25705087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
25715087abfbSRichard Henderson     tcg_temp_free_i64(t0);
25725087abfbSRichard Henderson     tcg_temp_free_i64(t1);
25735087abfbSRichard Henderson     tcg_temp_free_i64(t2);
25745087abfbSRichard Henderson }
25755087abfbSRichard Henderson 
2576b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2577b87fb8cdSRichard Henderson {
2578b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2579b87fb8cdSRichard Henderson }
2580b87fb8cdSRichard Henderson 
2581b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2582b87fb8cdSRichard Henderson {
2583b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2584b87fb8cdSRichard Henderson }
2585b87fb8cdSRichard Henderson 
2586b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2587b87fb8cdSRichard Henderson {
2588b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2589b87fb8cdSRichard Henderson }
2590b87fb8cdSRichard Henderson 
2591b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2592b87fb8cdSRichard Henderson {
2593b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2594b87fb8cdSRichard Henderson }
2595b87fb8cdSRichard Henderson 
2596ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
2597ff1f11f7SRichard Henderson {
2598ff1f11f7SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
2599ff1f11f7SRichard Henderson 
2600ff1f11f7SRichard Henderson     tcg_gen_sari_i64(t, a, 63);
2601ff1f11f7SRichard Henderson     tcg_gen_xor_i64(ret, a, t);
2602ff1f11f7SRichard Henderson     tcg_gen_sub_i64(ret, ret, t);
2603ff1f11f7SRichard Henderson     tcg_temp_free_i64(t);
2604ff1f11f7SRichard Henderson }
2605ff1f11f7SRichard Henderson 
2606951c6300SRichard Henderson /* Size changing operations.  */
2607951c6300SRichard Henderson 
2608609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2609951c6300SRichard Henderson {
26103a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2611951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2612609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2613b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2614ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2615951c6300SRichard Henderson     } else {
2616dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2617609ad705SRichard Henderson     }
2618609ad705SRichard Henderson }
2619609ad705SRichard Henderson 
2620609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2621609ad705SRichard Henderson {
2622609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2623609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2624609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2625b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2626ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2627951c6300SRichard Henderson     } else {
2628951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2629609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2630dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2631951c6300SRichard Henderson         tcg_temp_free_i64(t);
2632951c6300SRichard Henderson     }
2633951c6300SRichard Henderson }
2634951c6300SRichard Henderson 
2635951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2636951c6300SRichard Henderson {
26373a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2638951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2639951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
26403a13c3f3SRichard Henderson     } else {
2641b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2642ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26433a13c3f3SRichard Henderson     }
2644951c6300SRichard Henderson }
2645951c6300SRichard Henderson 
2646951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2647951c6300SRichard Henderson {
26483a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2649951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2650951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
26513a13c3f3SRichard Henderson     } else {
2652b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2653ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26543a13c3f3SRichard Henderson     }
2655951c6300SRichard Henderson }
2656951c6300SRichard Henderson 
2657951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2658951c6300SRichard Henderson {
26593a13c3f3SRichard Henderson     TCGv_i64 tmp;
26603a13c3f3SRichard Henderson 
26613a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2662951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2663951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
26643a13c3f3SRichard Henderson         return;
26653a13c3f3SRichard Henderson     }
26663a13c3f3SRichard Henderson 
26673a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2668951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2669951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2670951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2671951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2672951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2673951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2674951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2675951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2676951c6300SRichard Henderson     } else {
2677951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2678951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2679951c6300SRichard Henderson     }
2680951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2681951c6300SRichard Henderson }
2682951c6300SRichard Henderson 
2683951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2684951c6300SRichard Henderson {
26853a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2686951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2687951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
26883a13c3f3SRichard Henderson     } else {
2689609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2690609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
26913a13c3f3SRichard Henderson     }
2692951c6300SRichard Henderson }
2693951c6300SRichard Henderson 
2694951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2695951c6300SRichard Henderson {
2696951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2697951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2698951c6300SRichard Henderson }
2699951c6300SRichard Henderson 
2700951c6300SRichard Henderson /* QEMU specific operations.  */
2701951c6300SRichard Henderson 
2702d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
270307ea28b4SRichard Henderson {
2704eba40358SRichard Henderson     /*
2705eba40358SRichard Henderson      * Let the jit code return the read-only version of the
2706eba40358SRichard Henderson      * TranslationBlock, so that we minimize the pc-relative
2707eba40358SRichard Henderson      * distance of the address of the exit_tb code to TB.
2708eba40358SRichard Henderson      * This will improve utilization of pc-relative address loads.
2709eba40358SRichard Henderson      *
2710eba40358SRichard Henderson      * TODO: Move this to translator_loop, so that all const
2711eba40358SRichard Henderson      * TranslationBlock pointers refer to read-only memory.
2712eba40358SRichard Henderson      * This requires coordination with targets that do not use
2713eba40358SRichard Henderson      * the translator_loop.
2714eba40358SRichard Henderson      */
2715eba40358SRichard Henderson     uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx;
271607ea28b4SRichard Henderson 
271707ea28b4SRichard Henderson     if (tb == NULL) {
271807ea28b4SRichard Henderson         tcg_debug_assert(idx == 0);
271907ea28b4SRichard Henderson     } else if (idx <= TB_EXIT_IDXMAX) {
272007ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG
272107ea28b4SRichard Henderson         /* This is an exit following a goto_tb.  Verify that we have
272207ea28b4SRichard Henderson            seen this numbered exit before, via tcg_gen_goto_tb.  */
272307ea28b4SRichard Henderson         tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
272407ea28b4SRichard Henderson #endif
272507ea28b4SRichard Henderson     } else {
272607ea28b4SRichard Henderson         /* This is an exit via the exitreq label.  */
272707ea28b4SRichard Henderson         tcg_debug_assert(idx == TB_EXIT_REQUESTED);
272807ea28b4SRichard Henderson     }
272907ea28b4SRichard Henderson 
2730e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
273107ea28b4SRichard Henderson     tcg_gen_op1i(INDEX_op_exit_tb, val);
273207ea28b4SRichard Henderson }
273307ea28b4SRichard Henderson 
2734951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2735951c6300SRichard Henderson {
273684f15616SRichard Henderson     /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
273784f15616SRichard Henderson     tcg_debug_assert(!(tcg_ctx->tb_cflags & CF_NO_GOTO_TB));
2738951c6300SRichard Henderson     /* We only support two chained exits.  */
273907ea28b4SRichard Henderson     tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
2740951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2741a4761232SPhilippe Mathieu-Daudé     /* Verify that we haven't seen this numbered exit before.  */
2742b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2743b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2744951c6300SRichard Henderson #endif
2745e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2746951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2747951c6300SRichard Henderson }
2748951c6300SRichard Henderson 
27497f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2750cedbcb01SEmilio G. Cota {
2751e6d86bedSEmilio G. Cota     TCGv_ptr ptr;
2752e6d86bedSEmilio G. Cota 
275384f15616SRichard Henderson     if (tcg_ctx->tb_cflags & CF_NO_GOTO_PTR) {
275484f15616SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
275584f15616SRichard Henderson         return;
275684f15616SRichard Henderson     }
275784f15616SRichard Henderson 
2758e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2759e6d86bedSEmilio G. Cota     ptr = tcg_temp_new_ptr();
27601c2adb95SRichard Henderson     gen_helper_lookup_tb_ptr(ptr, cpu_env);
2761ae8b75dcSRichard Henderson     tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2762cedbcb01SEmilio G. Cota     tcg_temp_free_ptr(ptr);
2763cedbcb01SEmilio G. Cota }
2764cedbcb01SEmilio G. Cota 
276514776ab5STony Nguyen static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
2766951c6300SRichard Henderson {
27671f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
2768*76e366e7SRichard Henderson     unsigned a_bits = get_alignment_bits(op);
2769*76e366e7SRichard Henderson 
2770*76e366e7SRichard Henderson     /* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */
2771*76e366e7SRichard Henderson     if (a_bits == (op & MO_SIZE)) {
2772*76e366e7SRichard Henderson         op = (op & ~MO_AMASK) | MO_ALIGN;
2773*76e366e7SRichard Henderson     }
27741f00b27fSSergey Sorokin 
2775951c6300SRichard Henderson     switch (op & MO_SIZE) {
2776951c6300SRichard Henderson     case MO_8:
2777951c6300SRichard Henderson         op &= ~MO_BSWAP;
2778951c6300SRichard Henderson         break;
2779951c6300SRichard Henderson     case MO_16:
2780951c6300SRichard Henderson         break;
2781951c6300SRichard Henderson     case MO_32:
2782951c6300SRichard Henderson         if (!is64) {
2783951c6300SRichard Henderson             op &= ~MO_SIGN;
2784951c6300SRichard Henderson         }
2785951c6300SRichard Henderson         break;
2786951c6300SRichard Henderson     case MO_64:
27874b473e0cSRichard Henderson         if (is64) {
27884b473e0cSRichard Henderson             op &= ~MO_SIGN;
2789951c6300SRichard Henderson             break;
2790951c6300SRichard Henderson         }
27914b473e0cSRichard Henderson         /* fall through */
27924b473e0cSRichard Henderson     default:
27934b473e0cSRichard Henderson         g_assert_not_reached();
27944b473e0cSRichard Henderson     }
2795951c6300SRichard Henderson     if (st) {
2796951c6300SRichard Henderson         op &= ~MO_SIGN;
2797951c6300SRichard Henderson     }
2798951c6300SRichard Henderson     return op;
2799951c6300SRichard Henderson }
2800951c6300SRichard Henderson 
2801c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
280214776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2803951c6300SRichard Henderson {
28049002ffcbSRichard Henderson     MemOpIdx oi = make_memop_idx(memop, idx);
2805951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
280659227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2807951c6300SRichard Henderson #else
2808c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
280959227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2810c45cb8bbSRichard Henderson     } else {
2811ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2812c45cb8bbSRichard Henderson     }
2813951c6300SRichard Henderson #endif
2814c45cb8bbSRichard Henderson }
2815c45cb8bbSRichard Henderson 
2816c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
281714776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2818c45cb8bbSRichard Henderson {
28199002ffcbSRichard Henderson     MemOpIdx oi = make_memop_idx(memop, idx);
2820c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2821c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
282259227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2823c45cb8bbSRichard Henderson     } else {
2824ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2825c45cb8bbSRichard Henderson     }
2826c45cb8bbSRichard Henderson #else
2827c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
282859227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
282959227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2830c45cb8bbSRichard Henderson     } else {
283159227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2832c45cb8bbSRichard Henderson     }
2833c45cb8bbSRichard Henderson #endif
2834c45cb8bbSRichard Henderson }
2835951c6300SRichard Henderson 
2836b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2837b32dc337SPranith Kumar {
2838b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2839b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2840b32dc337SPranith Kumar #endif
2841b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2842b32dc337SPranith Kumar     if (type) {
2843b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2844b32dc337SPranith Kumar     }
2845b32dc337SPranith Kumar }
2846b32dc337SPranith Kumar 
2847fcc54ab5SAlex Bennée static inline TCGv plugin_prep_mem_callbacks(TCGv vaddr)
2848fcc54ab5SAlex Bennée {
2849fcc54ab5SAlex Bennée #ifdef CONFIG_PLUGIN
2850fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
2851fcc54ab5SAlex Bennée         /* Save a copy of the vaddr for use after a load.  */
2852fcc54ab5SAlex Bennée         TCGv temp = tcg_temp_new();
2853fcc54ab5SAlex Bennée         tcg_gen_mov_tl(temp, vaddr);
2854fcc54ab5SAlex Bennée         return temp;
2855fcc54ab5SAlex Bennée     }
2856fcc54ab5SAlex Bennée #endif
2857fcc54ab5SAlex Bennée     return vaddr;
2858fcc54ab5SAlex Bennée }
2859fcc54ab5SAlex Bennée 
286037aff087SRichard Henderson static void plugin_gen_mem_callbacks(TCGv vaddr, MemOpIdx oi,
286137aff087SRichard Henderson                                      enum qemu_plugin_mem_rw rw)
2862e6d86bedSEmilio G. Cota {
2863e6d86bedSEmilio G. Cota #ifdef CONFIG_PLUGIN
2864fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
286537aff087SRichard Henderson         qemu_plugin_meminfo_t info = make_plugin_meminfo(oi, rw);
2866e6d86bedSEmilio G. Cota         plugin_gen_empty_mem_callback(vaddr, info);
2867fcc54ab5SAlex Bennée         tcg_temp_free(vaddr);
2868fcc54ab5SAlex Bennée     }
2869e6d86bedSEmilio G. Cota #endif
2870e6d86bedSEmilio G. Cota }
2871e6d86bedSEmilio G. Cota 
287214776ab5STony Nguyen void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2873951c6300SRichard Henderson {
287414776ab5STony Nguyen     MemOp orig_memop;
287537aff087SRichard Henderson     MemOpIdx oi;
2876e1dcf352SRichard Henderson 
2877b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2878951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
287937aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
28800583f775SRichard Henderson     trace_guest_ld_before_tcg(tcg_ctx->cpu, cpu_env, addr, oi);
2881e1dcf352SRichard Henderson 
2882e1dcf352SRichard Henderson     orig_memop = memop;
2883e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2884e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2885359feba5SRichard Henderson         /* The bswap primitive benefits from zero-extended input.  */
2886e1dcf352SRichard Henderson         if ((memop & MO_SSIZE) == MO_SW) {
2887e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2888e1dcf352SRichard Henderson         }
2889e1dcf352SRichard Henderson     }
2890e1dcf352SRichard Henderson 
2891fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2892c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
289337aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R);
2894e1dcf352SRichard Henderson 
2895e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2896e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2897e1dcf352SRichard Henderson         case MO_16:
2898359feba5SRichard Henderson             tcg_gen_bswap16_i32(val, val, (orig_memop & MO_SIGN
2899359feba5SRichard Henderson                                            ? TCG_BSWAP_IZ | TCG_BSWAP_OS
2900359feba5SRichard Henderson                                            : TCG_BSWAP_IZ | TCG_BSWAP_OZ));
2901e1dcf352SRichard Henderson             break;
2902e1dcf352SRichard Henderson         case MO_32:
2903e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(val, val);
2904e1dcf352SRichard Henderson             break;
2905e1dcf352SRichard Henderson         default:
2906e1dcf352SRichard Henderson             g_assert_not_reached();
2907e1dcf352SRichard Henderson         }
2908e1dcf352SRichard Henderson     }
2909951c6300SRichard Henderson }
2910951c6300SRichard Henderson 
291114776ab5STony Nguyen void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2912951c6300SRichard Henderson {
2913e1dcf352SRichard Henderson     TCGv_i32 swap = NULL;
291437aff087SRichard Henderson     MemOpIdx oi;
2915e1dcf352SRichard Henderson 
2916b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2917951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
291837aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
29190583f775SRichard Henderson     trace_guest_st_before_tcg(tcg_ctx->cpu, cpu_env, addr, oi);
2920e1dcf352SRichard Henderson 
2921e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2922e1dcf352SRichard Henderson         swap = tcg_temp_new_i32();
2923e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
2924e1dcf352SRichard Henderson         case MO_16:
2925b53357acSRichard Henderson             tcg_gen_bswap16_i32(swap, val, 0);
2926e1dcf352SRichard Henderson             break;
2927e1dcf352SRichard Henderson         case MO_32:
2928e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(swap, val);
2929e1dcf352SRichard Henderson             break;
2930e1dcf352SRichard Henderson         default:
2931e1dcf352SRichard Henderson             g_assert_not_reached();
2932e1dcf352SRichard Henderson         }
2933e1dcf352SRichard Henderson         val = swap;
2934e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2935e1dcf352SRichard Henderson     }
2936e1dcf352SRichard Henderson 
2937fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
293807ce0b05SRichard Henderson     if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) {
293907ce0b05SRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx);
294007ce0b05SRichard Henderson     } else {
2941c45cb8bbSRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
294207ce0b05SRichard Henderson     }
294337aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
2944e1dcf352SRichard Henderson 
2945e1dcf352SRichard Henderson     if (swap) {
2946e1dcf352SRichard Henderson         tcg_temp_free_i32(swap);
2947e1dcf352SRichard Henderson     }
2948951c6300SRichard Henderson }
2949951c6300SRichard Henderson 
295014776ab5STony Nguyen void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
2951951c6300SRichard Henderson {
295214776ab5STony Nguyen     MemOp orig_memop;
295337aff087SRichard Henderson     MemOpIdx oi;
2954e1dcf352SRichard Henderson 
29553a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2956951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
2957951c6300SRichard Henderson         if (memop & MO_SIGN) {
2958951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
2959951c6300SRichard Henderson         } else {
2960951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
2961951c6300SRichard Henderson         }
2962951c6300SRichard Henderson         return;
2963951c6300SRichard Henderson     }
2964951c6300SRichard Henderson 
2965e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2966c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
296737aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
29680583f775SRichard Henderson     trace_guest_ld_before_tcg(tcg_ctx->cpu, cpu_env, addr, oi);
2969e1dcf352SRichard Henderson 
2970e1dcf352SRichard Henderson     orig_memop = memop;
2971e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2972e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2973359feba5SRichard Henderson         /* The bswap primitive benefits from zero-extended input.  */
2974e1dcf352SRichard Henderson         if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
2975e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2976e1dcf352SRichard Henderson         }
2977e1dcf352SRichard Henderson     }
2978e1dcf352SRichard Henderson 
2979fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2980c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
298137aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R);
2982e1dcf352SRichard Henderson 
2983e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2984359feba5SRichard Henderson         int flags = (orig_memop & MO_SIGN
2985359feba5SRichard Henderson                      ? TCG_BSWAP_IZ | TCG_BSWAP_OS
2986359feba5SRichard Henderson                      : TCG_BSWAP_IZ | TCG_BSWAP_OZ);
2987e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2988e1dcf352SRichard Henderson         case MO_16:
2989359feba5SRichard Henderson             tcg_gen_bswap16_i64(val, val, flags);
2990e1dcf352SRichard Henderson             break;
2991e1dcf352SRichard Henderson         case MO_32:
2992359feba5SRichard Henderson             tcg_gen_bswap32_i64(val, val, flags);
2993e1dcf352SRichard Henderson             break;
2994e1dcf352SRichard Henderson         case MO_64:
2995e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(val, val);
2996e1dcf352SRichard Henderson             break;
2997e1dcf352SRichard Henderson         default:
2998e1dcf352SRichard Henderson             g_assert_not_reached();
2999e1dcf352SRichard Henderson         }
3000e1dcf352SRichard Henderson     }
3001951c6300SRichard Henderson }
3002951c6300SRichard Henderson 
300314776ab5STony Nguyen void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
3004951c6300SRichard Henderson {
3005e1dcf352SRichard Henderson     TCGv_i64 swap = NULL;
300637aff087SRichard Henderson     MemOpIdx oi;
3007e1dcf352SRichard Henderson 
30083a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
3009951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
3010951c6300SRichard Henderson         return;
3011951c6300SRichard Henderson     }
3012951c6300SRichard Henderson 
3013e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
3014c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
301537aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
30160583f775SRichard Henderson     trace_guest_st_before_tcg(tcg_ctx->cpu, cpu_env, addr, oi);
3017e1dcf352SRichard Henderson 
3018e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
3019e1dcf352SRichard Henderson         swap = tcg_temp_new_i64();
3020e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
3021e1dcf352SRichard Henderson         case MO_16:
3022b53357acSRichard Henderson             tcg_gen_bswap16_i64(swap, val, 0);
3023e1dcf352SRichard Henderson             break;
3024e1dcf352SRichard Henderson         case MO_32:
3025b53357acSRichard Henderson             tcg_gen_bswap32_i64(swap, val, 0);
3026e1dcf352SRichard Henderson             break;
3027e1dcf352SRichard Henderson         case MO_64:
3028e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(swap, val);
3029e1dcf352SRichard Henderson             break;
3030e1dcf352SRichard Henderson         default:
3031e1dcf352SRichard Henderson             g_assert_not_reached();
3032e1dcf352SRichard Henderson         }
3033e1dcf352SRichard Henderson         val = swap;
3034e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
3035e1dcf352SRichard Henderson     }
3036e1dcf352SRichard Henderson 
3037fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
3038c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
303937aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
3040e1dcf352SRichard Henderson 
3041e1dcf352SRichard Henderson     if (swap) {
3042e1dcf352SRichard Henderson         tcg_temp_free_i64(swap);
3043e1dcf352SRichard Henderson     }
3044951c6300SRichard Henderson }
3045c482cb11SRichard Henderson 
304614776ab5STony Nguyen static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
3047c482cb11SRichard Henderson {
3048c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3049c482cb11SRichard Henderson     case MO_SB:
3050c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
3051c482cb11SRichard Henderson         break;
3052c482cb11SRichard Henderson     case MO_UB:
3053c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
3054c482cb11SRichard Henderson         break;
3055c482cb11SRichard Henderson     case MO_SW:
3056c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
3057c482cb11SRichard Henderson         break;
3058c482cb11SRichard Henderson     case MO_UW:
3059c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
3060c482cb11SRichard Henderson         break;
3061c482cb11SRichard Henderson     default:
3062c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
3063c482cb11SRichard Henderson         break;
3064c482cb11SRichard Henderson     }
3065c482cb11SRichard Henderson }
3066c482cb11SRichard Henderson 
306714776ab5STony Nguyen static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
3068c482cb11SRichard Henderson {
3069c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3070c482cb11SRichard Henderson     case MO_SB:
3071c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
3072c482cb11SRichard Henderson         break;
3073c482cb11SRichard Henderson     case MO_UB:
3074c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
3075c482cb11SRichard Henderson         break;
3076c482cb11SRichard Henderson     case MO_SW:
3077c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
3078c482cb11SRichard Henderson         break;
3079c482cb11SRichard Henderson     case MO_UW:
3080c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
3081c482cb11SRichard Henderson         break;
3082c482cb11SRichard Henderson     case MO_SL:
3083c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
3084c482cb11SRichard Henderson         break;
3085c482cb11SRichard Henderson     case MO_UL:
3086c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
3087c482cb11SRichard Henderson         break;
3088c482cb11SRichard Henderson     default:
3089c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
3090c482cb11SRichard Henderson         break;
3091c482cb11SRichard Henderson     }
3092c482cb11SRichard Henderson }
3093c482cb11SRichard Henderson 
3094c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
3095c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
3096c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
3097c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
3098c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
3099c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
3100c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
3101c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
3102c482cb11SRichard Henderson 
3103df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3104df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
3105df79b996SRichard Henderson #else
3106df79b996SRichard Henderson # define WITH_ATOMIC64(X)
3107df79b996SRichard Henderson #endif
3108df79b996SRichard Henderson 
31094b473e0cSRichard Henderson static void * const table_cmpxchg[(MO_SIZE | MO_BSWAP) + 1] = {
3110c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
3111c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
3112c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
3113c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
3114c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
3115df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
3116df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
3117c482cb11SRichard Henderson };
3118c482cb11SRichard Henderson 
3119c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
312014776ab5STony Nguyen                                 TCGv_i32 newv, TCGArg idx, MemOp memop)
3121c482cb11SRichard Henderson {
3122c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3123c482cb11SRichard Henderson 
3124b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
3125c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
3126c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
3127c482cb11SRichard Henderson 
3128c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
3129c482cb11SRichard Henderson 
3130c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
3131c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
3132c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3133c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
3134c482cb11SRichard Henderson 
3135c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3136c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
3137c482cb11SRichard Henderson         } else {
3138c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
3139c482cb11SRichard Henderson         }
3140c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
3141c482cb11SRichard Henderson     } else {
3142c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
31439002ffcbSRichard Henderson         MemOpIdx oi;
3144c482cb11SRichard Henderson 
3145c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3146c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3147c482cb11SRichard Henderson 
3148e28a8664SRichard Henderson         oi = make_memop_idx(memop & ~MO_SIGN, idx);
314911d11d61SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3150c482cb11SRichard Henderson 
3151c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3152c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
3153c482cb11SRichard Henderson         }
3154c482cb11SRichard Henderson     }
3155c482cb11SRichard Henderson }
3156c482cb11SRichard Henderson 
3157c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
315814776ab5STony Nguyen                                 TCGv_i64 newv, TCGArg idx, MemOp memop)
3159c482cb11SRichard Henderson {
3160c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3161c482cb11SRichard Henderson 
3162b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
3163c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
3164c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
3165c482cb11SRichard Henderson 
3166c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
3167c482cb11SRichard Henderson 
3168c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
3169c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
3170c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3171c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
3172c482cb11SRichard Henderson 
3173c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3174c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
3175c482cb11SRichard Henderson         } else {
3176c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
3177c482cb11SRichard Henderson         }
3178c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
3179c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
3180df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3181c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
31829002ffcbSRichard Henderson         MemOpIdx oi;
3183c482cb11SRichard Henderson 
3184c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3185c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3186c482cb11SRichard Henderson 
3187e28a8664SRichard Henderson         oi = make_memop_idx(memop, idx);
318811d11d61SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3189df79b996SRichard Henderson #else
31901c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
319179b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
319279b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
319379b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
3194df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3195c482cb11SRichard Henderson     } else {
3196c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
3197c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
3198c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3199c482cb11SRichard Henderson 
3200c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
3201c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
3202c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
3203c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
3204c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
3205c482cb11SRichard Henderson 
3206c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
3207c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3208c482cb11SRichard Henderson 
3209c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3210c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
3211c482cb11SRichard Henderson         }
3212c482cb11SRichard Henderson     }
3213c482cb11SRichard Henderson }
3214c482cb11SRichard Henderson 
3215c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
321614776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3217c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
3218c482cb11SRichard Henderson {
3219c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
3220c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
3221c482cb11SRichard Henderson 
3222c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3223c482cb11SRichard Henderson 
3224852f933eSRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop);
3225852f933eSRichard Henderson     tcg_gen_ext_i32(t2, val, memop);
3226852f933eSRichard Henderson     gen(t2, t1, t2);
3227c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3228c482cb11SRichard Henderson 
3229c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
3230c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
3231c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
3232c482cb11SRichard Henderson }
3233c482cb11SRichard Henderson 
3234c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
323514776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3236c482cb11SRichard Henderson {
3237c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
32389002ffcbSRichard Henderson     MemOpIdx oi;
3239c482cb11SRichard Henderson 
3240c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3241c482cb11SRichard Henderson 
3242c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
3243c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
3244c482cb11SRichard Henderson 
3245e28a8664SRichard Henderson     oi = make_memop_idx(memop & ~MO_SIGN, idx);
324611d11d61SRichard Henderson     gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
3247c482cb11SRichard Henderson 
3248c482cb11SRichard Henderson     if (memop & MO_SIGN) {
3249c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
3250c482cb11SRichard Henderson     }
3251c482cb11SRichard Henderson }
3252c482cb11SRichard Henderson 
3253c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
325414776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3255c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
3256c482cb11SRichard Henderson {
3257c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3258c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3259c482cb11SRichard Henderson 
3260c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3261c482cb11SRichard Henderson 
3262852f933eSRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop);
3263852f933eSRichard Henderson     tcg_gen_ext_i64(t2, val, memop);
3264852f933eSRichard Henderson     gen(t2, t1, t2);
3265c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3266c482cb11SRichard Henderson 
3267c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
3268c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
3269c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
3270c482cb11SRichard Henderson }
3271c482cb11SRichard Henderson 
3272c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
327314776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3274c482cb11SRichard Henderson {
3275c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3276c482cb11SRichard Henderson 
3277c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
3278df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3279c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
32809002ffcbSRichard Henderson         MemOpIdx oi;
3281c482cb11SRichard Henderson 
3282c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
3283c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3284c482cb11SRichard Henderson 
3285e28a8664SRichard Henderson         oi = make_memop_idx(memop & ~MO_SIGN, idx);
328611d11d61SRichard Henderson         gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
3287df79b996SRichard Henderson #else
32881c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
328979b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
329079b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
329179b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
3292df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3293c482cb11SRichard Henderson     } else {
3294c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
3295c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3296c482cb11SRichard Henderson 
3297c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
3298c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
3299c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
3300c482cb11SRichard Henderson 
3301c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
3302c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3303c482cb11SRichard Henderson 
3304c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3305c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
3306c482cb11SRichard Henderson         }
3307c482cb11SRichard Henderson     }
3308c482cb11SRichard Henderson }
3309c482cb11SRichard Henderson 
3310c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
33114b473e0cSRichard Henderson static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = {          \
3312c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
3313c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
3314c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
3315c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
3316c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
3317df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
3318df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3319c482cb11SRichard Henderson };                                                                      \
3320c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
332114776ab5STony Nguyen     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop)    \
3322c482cb11SRichard Henderson {                                                                       \
3323b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3324c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3325c482cb11SRichard Henderson     } else {                                                            \
3326c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3327c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3328c482cb11SRichard Henderson     }                                                                   \
3329c482cb11SRichard Henderson }                                                                       \
3330c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
333114776ab5STony Nguyen     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop)    \
3332c482cb11SRichard Henderson {                                                                       \
3333b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3334c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3335c482cb11SRichard Henderson     } else {                                                            \
3336c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3337c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3338c482cb11SRichard Henderson     }                                                                   \
3339c482cb11SRichard Henderson }
3340c482cb11SRichard Henderson 
3341c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3342c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3343c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3344c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
33455507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smin, smin, 0)
33465507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umin, umin, 0)
33475507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smax, smax, 0)
33485507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umax, umax, 0)
3349c482cb11SRichard Henderson 
3350c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3351c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3352c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3353c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
33545507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smin_fetch, smin, 1)
33555507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umin_fetch, umin, 1)
33565507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smax_fetch, smax, 1)
33575507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umax_fetch, umax, 1)
3358c482cb11SRichard Henderson 
3359c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3360c482cb11SRichard Henderson {
3361c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3362c482cb11SRichard Henderson }
3363c482cb11SRichard Henderson 
3364c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3365c482cb11SRichard Henderson {
3366c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3367c482cb11SRichard Henderson }
3368c482cb11SRichard Henderson 
3369c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3370c482cb11SRichard Henderson 
3371c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3372