xref: /openbmc/qemu/tcg/tcg-op.c (revision 4771e71c)
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"
30e6d86bedSEmilio G. Cota #include "exec/plugin-gen.h"
31d56fea79SRichard Henderson #include "tcg-internal.h"
32951c6300SRichard Henderson 
33951c6300SRichard Henderson 
34b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
35951c6300SRichard Henderson {
36d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 1);
3775e8b9b7SRichard Henderson     op->args[0] = a1;
38951c6300SRichard Henderson }
39951c6300SRichard Henderson 
40b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
41951c6300SRichard Henderson {
42d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 2);
4375e8b9b7SRichard Henderson     op->args[0] = a1;
4475e8b9b7SRichard Henderson     op->args[1] = a2;
45951c6300SRichard Henderson }
46951c6300SRichard Henderson 
47b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
48951c6300SRichard Henderson {
49d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 3);
5075e8b9b7SRichard Henderson     op->args[0] = a1;
5175e8b9b7SRichard Henderson     op->args[1] = a2;
5275e8b9b7SRichard Henderson     op->args[2] = a3;
53951c6300SRichard Henderson }
54951c6300SRichard Henderson 
55b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
56951c6300SRichard Henderson {
57d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 4);
5875e8b9b7SRichard Henderson     op->args[0] = a1;
5975e8b9b7SRichard Henderson     op->args[1] = a2;
6075e8b9b7SRichard Henderson     op->args[2] = a3;
6175e8b9b7SRichard Henderson     op->args[3] = a4;
62951c6300SRichard Henderson }
63951c6300SRichard Henderson 
64b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
65b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5)
66951c6300SRichard Henderson {
67d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 5);
6875e8b9b7SRichard Henderson     op->args[0] = a1;
6975e8b9b7SRichard Henderson     op->args[1] = a2;
7075e8b9b7SRichard Henderson     op->args[2] = a3;
7175e8b9b7SRichard Henderson     op->args[3] = a4;
7275e8b9b7SRichard Henderson     op->args[4] = a5;
73951c6300SRichard Henderson }
74951c6300SRichard Henderson 
75b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
76b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5, TCGArg a6)
77951c6300SRichard Henderson {
78d4478943SPhilippe Mathieu-Daudé     TCGOp *op = tcg_emit_op(opc, 6);
7975e8b9b7SRichard Henderson     op->args[0] = a1;
8075e8b9b7SRichard Henderson     op->args[1] = a2;
8175e8b9b7SRichard Henderson     op->args[2] = a3;
8275e8b9b7SRichard Henderson     op->args[3] = a4;
8375e8b9b7SRichard Henderson     op->args[4] = a5;
8475e8b9b7SRichard Henderson     op->args[5] = a6;
85951c6300SRichard Henderson }
86951c6300SRichard Henderson 
87f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
88f65e19bcSPranith Kumar {
89b7e4afbdSRichard Henderson     if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) {
90b7e8b17aSRichard Henderson         tcg_gen_op1(INDEX_op_mb, mb_type);
91f65e19bcSPranith Kumar     }
92f65e19bcSPranith Kumar }
93f65e19bcSPranith Kumar 
94951c6300SRichard Henderson /* 32 bit ops */
95951c6300SRichard Henderson 
9611d11d61SRichard Henderson void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
9711d11d61SRichard Henderson {
9811d11d61SRichard Henderson     tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
9911d11d61SRichard Henderson }
10011d11d61SRichard Henderson 
101951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
102951c6300SRichard Henderson {
103951c6300SRichard Henderson     /* some cases can be optimized here */
104951c6300SRichard Henderson     if (arg2 == 0) {
105951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
106951c6300SRichard Henderson     } else {
10711d11d61SRichard Henderson         tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
108951c6300SRichard Henderson     }
109951c6300SRichard Henderson }
110951c6300SRichard Henderson 
111951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
112951c6300SRichard Henderson {
113951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
114951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
115951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
116951c6300SRichard Henderson     } else {
11711d11d61SRichard Henderson         tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
118951c6300SRichard Henderson     }
119951c6300SRichard Henderson }
120951c6300SRichard Henderson 
121951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
122951c6300SRichard Henderson {
123951c6300SRichard Henderson     /* some cases can be optimized here */
124951c6300SRichard Henderson     if (arg2 == 0) {
125951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
126951c6300SRichard Henderson     } else {
12711d11d61SRichard Henderson         tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
128951c6300SRichard Henderson     }
129951c6300SRichard Henderson }
130951c6300SRichard Henderson 
131474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
132951c6300SRichard Henderson {
133951c6300SRichard Henderson     /* Some cases can be optimized here.  */
134951c6300SRichard Henderson     switch (arg2) {
135951c6300SRichard Henderson     case 0:
136951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
137951c6300SRichard Henderson         return;
138474b2e8fSRichard Henderson     case -1:
139951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
140951c6300SRichard Henderson         return;
141474b2e8fSRichard Henderson     case 0xff:
142951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
143951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
144951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
145951c6300SRichard Henderson             return;
146951c6300SRichard Henderson         }
147951c6300SRichard Henderson         break;
148474b2e8fSRichard Henderson     case 0xffff:
149951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
150951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
151951c6300SRichard Henderson             return;
152951c6300SRichard Henderson         }
153951c6300SRichard Henderson         break;
154951c6300SRichard Henderson     }
15511d11d61SRichard Henderson 
15611d11d61SRichard Henderson     tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
157951c6300SRichard Henderson }
158951c6300SRichard Henderson 
159951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
160951c6300SRichard Henderson {
161951c6300SRichard Henderson     /* Some cases can be optimized here.  */
162951c6300SRichard Henderson     if (arg2 == -1) {
163951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
164951c6300SRichard Henderson     } else if (arg2 == 0) {
165951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
166951c6300SRichard Henderson     } else {
16711d11d61SRichard Henderson         tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
168951c6300SRichard Henderson     }
169951c6300SRichard Henderson }
170951c6300SRichard Henderson 
171951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
172951c6300SRichard Henderson {
173951c6300SRichard Henderson     /* Some cases can be optimized here.  */
174951c6300SRichard Henderson     if (arg2 == 0) {
175951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
176951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
177951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
178951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
179951c6300SRichard Henderson     } else {
18011d11d61SRichard Henderson         tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
181951c6300SRichard Henderson     }
182951c6300SRichard Henderson }
183951c6300SRichard Henderson 
184474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
185951c6300SRichard Henderson {
186474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
187951c6300SRichard Henderson     if (arg2 == 0) {
188951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
189951c6300SRichard Henderson     } else {
19011d11d61SRichard Henderson         tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2));
191951c6300SRichard Henderson     }
192951c6300SRichard Henderson }
193951c6300SRichard Henderson 
194474b2e8fSRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
195951c6300SRichard Henderson {
196474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
197951c6300SRichard Henderson     if (arg2 == 0) {
198951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
199951c6300SRichard Henderson     } else {
20011d11d61SRichard Henderson         tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2));
201951c6300SRichard Henderson     }
202951c6300SRichard Henderson }
203951c6300SRichard Henderson 
204474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
205951c6300SRichard Henderson {
206474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
207951c6300SRichard Henderson     if (arg2 == 0) {
208951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
209951c6300SRichard Henderson     } else {
21011d11d61SRichard Henderson         tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2));
211951c6300SRichard Henderson     }
212951c6300SRichard Henderson }
213951c6300SRichard Henderson 
21442a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
215951c6300SRichard Henderson {
216951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
21742a268c2SRichard Henderson         tcg_gen_br(l);
218951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
219d88a117eSRichard Henderson         l->refs++;
22042a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
221951c6300SRichard Henderson     }
222951c6300SRichard Henderson }
223951c6300SRichard Henderson 
22442a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
225951c6300SRichard Henderson {
22637ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
22737ed3bf1SRichard Henderson         tcg_gen_br(l);
22837ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
22911d11d61SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l);
230951c6300SRichard Henderson     }
23137ed3bf1SRichard Henderson }
232951c6300SRichard Henderson 
233951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
234951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
235951c6300SRichard Henderson {
236951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
237951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
238951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
239951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
240951c6300SRichard Henderson     } else {
241951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
242951c6300SRichard Henderson     }
243951c6300SRichard Henderson }
244951c6300SRichard Henderson 
245951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
246951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
247951c6300SRichard Henderson {
24811d11d61SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2));
249951c6300SRichard Henderson }
250951c6300SRichard Henderson 
251951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
252951c6300SRichard Henderson {
253b2e3ae94SRichard Henderson     if (arg2 == 0) {
254b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
255b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
256b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
257b2e3ae94SRichard Henderson     } else {
25811d11d61SRichard Henderson         tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2));
259951c6300SRichard Henderson     }
260b2e3ae94SRichard Henderson }
261951c6300SRichard Henderson 
262951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
263951c6300SRichard Henderson {
264951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
265951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
266951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
267951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
268951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
269951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
270951c6300SRichard Henderson         tcg_temp_free_i32(t0);
271951c6300SRichard Henderson     } else {
272951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
273951c6300SRichard Henderson     }
274951c6300SRichard Henderson }
275951c6300SRichard Henderson 
276951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
277951c6300SRichard Henderson {
278951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
279951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
280951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
281951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
282951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
283951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
284951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
285951c6300SRichard Henderson         tcg_temp_free_i32(t0);
286951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
287951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
288951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
289951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
290951c6300SRichard Henderson         tcg_temp_free_i32(t0);
291951c6300SRichard Henderson     } else {
292951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
293951c6300SRichard Henderson     }
294951c6300SRichard Henderson }
295951c6300SRichard Henderson 
296951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
297951c6300SRichard Henderson {
298951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
299951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
300951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
301951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
302951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
303951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
304951c6300SRichard Henderson         tcg_temp_free_i32(t0);
305951c6300SRichard Henderson     } else {
306951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
307951c6300SRichard Henderson     }
308951c6300SRichard Henderson }
309951c6300SRichard Henderson 
310951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
311951c6300SRichard Henderson {
312951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
313951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
314951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
315951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
316951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
317951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
318951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
319951c6300SRichard Henderson         tcg_temp_free_i32(t0);
320951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
321951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
322951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
323951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
324951c6300SRichard Henderson         tcg_temp_free_i32(t0);
325951c6300SRichard Henderson     } else {
326951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
327951c6300SRichard Henderson     }
328951c6300SRichard Henderson }
329951c6300SRichard Henderson 
330951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
331951c6300SRichard Henderson {
332951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
333951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
334951c6300SRichard Henderson     } else {
335951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
336951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
337951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
338951c6300SRichard Henderson         tcg_temp_free_i32(t0);
339951c6300SRichard Henderson     }
340951c6300SRichard Henderson }
341951c6300SRichard Henderson 
342951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
343951c6300SRichard Henderson {
344951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
345951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
346951c6300SRichard Henderson     } else {
347951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
348951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
349951c6300SRichard Henderson     }
350951c6300SRichard Henderson }
351951c6300SRichard Henderson 
352951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
353951c6300SRichard Henderson {
354951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
355951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
356951c6300SRichard Henderson     } else {
357951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
358951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
359951c6300SRichard Henderson     }
360951c6300SRichard Henderson }
361951c6300SRichard Henderson 
362951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
363951c6300SRichard Henderson {
364951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
365951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
366951c6300SRichard Henderson     } else {
367951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
368951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
369951c6300SRichard Henderson     }
370951c6300SRichard Henderson }
371951c6300SRichard Henderson 
372951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
373951c6300SRichard Henderson {
374951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
375951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
376951c6300SRichard Henderson     } else {
377951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
378951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
379951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
380951c6300SRichard Henderson         tcg_temp_free_i32(t0);
381951c6300SRichard Henderson     }
382951c6300SRichard Henderson }
383951c6300SRichard Henderson 
3840e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
3850e28d006SRichard Henderson {
3860e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
3870e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
3880e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
3890e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
3900e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
3910e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
3920e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
3930e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
3940e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
3950e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
3960e28d006SRichard Henderson         tcg_temp_free_i64(t1);
3970e28d006SRichard Henderson         tcg_temp_free_i64(t2);
3980e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
3990e28d006SRichard Henderson     } else {
4000e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4010e28d006SRichard Henderson     }
4020e28d006SRichard Henderson }
4030e28d006SRichard Henderson 
4040e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4050e28d006SRichard Henderson {
40611d11d61SRichard Henderson     tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2));
4070e28d006SRichard Henderson }
4080e28d006SRichard Henderson 
4090e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4100e28d006SRichard Henderson {
4110e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4120e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4130e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4140e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4150e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4160e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4170e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4180e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4190e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4200e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4210e28d006SRichard Henderson         tcg_temp_free_i64(t2);
42214e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
42314e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
42414e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
42514e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
42614e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
42714e99210SRichard Henderson 
42814e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
42914e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
43014e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
43114e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
43214e99210SRichard Henderson         } else {
43314e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
43414e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
43514e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
43614e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
43714e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
43814e99210SRichard Henderson         }
43911d11d61SRichard Henderson         z = tcg_constant_i32(0);
44014e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
44114e99210SRichard Henderson         tcg_temp_free_i32(t);
4420e28d006SRichard Henderson     } else {
4430e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4440e28d006SRichard Henderson     }
4450e28d006SRichard Henderson }
4460e28d006SRichard Henderson 
4470e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4480e28d006SRichard Henderson {
44914e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
45014e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
45114e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
45214e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
45314e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
45414e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
45514e99210SRichard Henderson         tcg_temp_free_i32(t);
45614e99210SRichard Henderson     } else {
45711d11d61SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2));
4580e28d006SRichard Henderson     }
45914e99210SRichard Henderson }
4600e28d006SRichard Henderson 
461086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
462086920c2SRichard Henderson {
463086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
464086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
465086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
466086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
467086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
468086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
469086920c2SRichard Henderson         tcg_temp_free_i32(t);
470086920c2SRichard Henderson     } else {
471086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
472086920c2SRichard Henderson     }
473086920c2SRichard Henderson }
474086920c2SRichard Henderson 
475a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
476a768e4e9SRichard Henderson {
477a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
478a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
479a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
480a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
481a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
482a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
483a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
484a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
485a768e4e9SRichard Henderson     } else {
486a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
487a768e4e9SRichard Henderson     }
488a768e4e9SRichard Henderson }
489a768e4e9SRichard Henderson 
490951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
491951c6300SRichard Henderson {
492951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
493951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
494951c6300SRichard Henderson     } else {
495951c6300SRichard Henderson         TCGv_i32 t0, t1;
496951c6300SRichard Henderson 
497951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
498951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
499951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
500951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
501951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
502951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
503951c6300SRichard Henderson         tcg_temp_free_i32(t0);
504951c6300SRichard Henderson         tcg_temp_free_i32(t1);
505951c6300SRichard Henderson     }
506951c6300SRichard Henderson }
507951c6300SRichard Henderson 
50807dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
509951c6300SRichard Henderson {
51007dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
511951c6300SRichard Henderson     /* some cases can be optimized here */
512951c6300SRichard Henderson     if (arg2 == 0) {
513951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
514951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
51511d11d61SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2));
516951c6300SRichard Henderson     } else {
517951c6300SRichard Henderson         TCGv_i32 t0, t1;
518951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
519951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
520951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
521951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
522951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
523951c6300SRichard Henderson         tcg_temp_free_i32(t0);
524951c6300SRichard Henderson         tcg_temp_free_i32(t1);
525951c6300SRichard Henderson     }
526951c6300SRichard Henderson }
527951c6300SRichard Henderson 
528951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
529951c6300SRichard Henderson {
530951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
531951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
532951c6300SRichard Henderson     } else {
533951c6300SRichard Henderson         TCGv_i32 t0, t1;
534951c6300SRichard Henderson 
535951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
536951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
537951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
538951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
539951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
540951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
541951c6300SRichard Henderson         tcg_temp_free_i32(t0);
542951c6300SRichard Henderson         tcg_temp_free_i32(t1);
543951c6300SRichard Henderson     }
544951c6300SRichard Henderson }
545951c6300SRichard Henderson 
54607dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
547951c6300SRichard Henderson {
54807dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
549951c6300SRichard Henderson     /* some cases can be optimized here */
550951c6300SRichard Henderson     if (arg2 == 0) {
551951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
552951c6300SRichard Henderson     } else {
553951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
554951c6300SRichard Henderson     }
555951c6300SRichard Henderson }
556951c6300SRichard Henderson 
557951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
558951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
559951c6300SRichard Henderson {
560951c6300SRichard Henderson     uint32_t mask;
561951c6300SRichard Henderson     TCGv_i32 t1;
562951c6300SRichard Henderson 
563951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
5640d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
565951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
566951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
567951c6300SRichard Henderson 
5680d0d309dSRichard Henderson     if (len == 32) {
569951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
570951c6300SRichard Henderson         return;
571951c6300SRichard Henderson     }
572951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
573951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
574951c6300SRichard Henderson         return;
575951c6300SRichard Henderson     }
576951c6300SRichard Henderson 
577951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
578951c6300SRichard Henderson 
579b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i32) {
580b0a60567SRichard Henderson         if (ofs + len == 32) {
581b0a60567SRichard Henderson             tcg_gen_shli_i32(t1, arg1, len);
582b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, t1, arg2, len);
583b0a60567SRichard Henderson             goto done;
584b0a60567SRichard Henderson         }
585b0a60567SRichard Henderson         if (ofs == 0) {
586b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, arg1, arg2, len);
587b0a60567SRichard Henderson             tcg_gen_rotli_i32(ret, ret, len);
588b0a60567SRichard Henderson             goto done;
589b0a60567SRichard Henderson         }
590b0a60567SRichard Henderson     }
591b0a60567SRichard Henderson 
592b0a60567SRichard Henderson     mask = (1u << len) - 1;
593951c6300SRichard Henderson     if (ofs + len < 32) {
594951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
595951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
596951c6300SRichard Henderson     } else {
597951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
598951c6300SRichard Henderson     }
599951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
600951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
601b0a60567SRichard Henderson  done:
602951c6300SRichard Henderson     tcg_temp_free_i32(t1);
603951c6300SRichard Henderson }
604951c6300SRichard Henderson 
60507cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
60607cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
60707cc68d5SRichard Henderson {
60807cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
60907cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
61007cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
61107cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
61207cc68d5SRichard Henderson 
61307cc68d5SRichard Henderson     if (ofs + len == 32) {
61407cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
61507cc68d5SRichard Henderson     } else if (ofs == 0) {
61607cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
61707cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
61807cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
61911d11d61SRichard Henderson         TCGv_i32 zero = tcg_constant_i32(0);
62007cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
62107cc68d5SRichard Henderson     } else {
62207cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
62307cc68d5SRichard Henderson            which allows ARG to stay live.  */
62407cc68d5SRichard Henderson         switch (len) {
62507cc68d5SRichard Henderson         case 16:
62607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
62707cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
62807cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
62907cc68d5SRichard Henderson                 return;
63007cc68d5SRichard Henderson             }
63107cc68d5SRichard Henderson             break;
63207cc68d5SRichard Henderson         case 8:
63307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
63407cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
63507cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
63607cc68d5SRichard Henderson                 return;
63707cc68d5SRichard Henderson             }
63807cc68d5SRichard Henderson             break;
63907cc68d5SRichard Henderson         }
64007cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
64107cc68d5SRichard Henderson         switch (ofs + len) {
64207cc68d5SRichard Henderson         case 16:
64307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
64407cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
64507cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
64607cc68d5SRichard Henderson                 return;
64707cc68d5SRichard Henderson             }
64807cc68d5SRichard Henderson             break;
64907cc68d5SRichard Henderson         case 8:
65007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
65107cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
65207cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
65307cc68d5SRichard Henderson                 return;
65407cc68d5SRichard Henderson             }
65507cc68d5SRichard Henderson             break;
65607cc68d5SRichard Henderson         }
65707cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
65807cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
65907cc68d5SRichard Henderson     }
66007cc68d5SRichard Henderson }
66107cc68d5SRichard Henderson 
6627ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
6637ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
6647ec8bab3SRichard Henderson {
6657ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
6667ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
6677ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
6687ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
6697ec8bab3SRichard Henderson 
6707ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
6717ec8bab3SRichard Henderson     if (ofs + len == 32) {
6727ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
6737ec8bab3SRichard Henderson         return;
6747ec8bab3SRichard Henderson     }
6757ec8bab3SRichard Henderson     if (ofs == 0) {
6767ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
6777ec8bab3SRichard Henderson         return;
6787ec8bab3SRichard Henderson     }
6797ec8bab3SRichard Henderson 
6807ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
6817ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
6827ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
6837ec8bab3SRichard Henderson         return;
6847ec8bab3SRichard Henderson     }
6857ec8bab3SRichard Henderson 
6867ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
6877ec8bab3SRichard Henderson     switch (ofs + len) {
6887ec8bab3SRichard Henderson     case 16:
6897ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
6907ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
6917ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
6927ec8bab3SRichard Henderson             return;
6937ec8bab3SRichard Henderson         }
6947ec8bab3SRichard Henderson         break;
6957ec8bab3SRichard Henderson     case 8:
6967ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
6977ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
6987ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
6997ec8bab3SRichard Henderson             return;
7007ec8bab3SRichard Henderson         }
7017ec8bab3SRichard Henderson         break;
7027ec8bab3SRichard Henderson     }
7037ec8bab3SRichard Henderson 
7047ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7057ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7067ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7077ec8bab3SRichard Henderson     switch (len) {
7087ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7097ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7107ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7117ec8bab3SRichard Henderson         break;
7127ec8bab3SRichard Henderson     default:
7137ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7147ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7157ec8bab3SRichard Henderson         break;
7167ec8bab3SRichard Henderson     }
7177ec8bab3SRichard Henderson }
7187ec8bab3SRichard Henderson 
7197ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7207ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7217ec8bab3SRichard Henderson {
7227ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7237ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7247ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7257ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7267ec8bab3SRichard Henderson 
7277ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7287ec8bab3SRichard Henderson     if (ofs + len == 32) {
7297ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7307ec8bab3SRichard Henderson         return;
7317ec8bab3SRichard Henderson     }
7327ec8bab3SRichard Henderson     if (ofs == 0) {
7337ec8bab3SRichard Henderson         switch (len) {
7347ec8bab3SRichard Henderson         case 16:
7357ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7367ec8bab3SRichard Henderson             return;
7377ec8bab3SRichard Henderson         case 8:
7387ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7397ec8bab3SRichard Henderson             return;
7407ec8bab3SRichard Henderson         }
7417ec8bab3SRichard Henderson     }
7427ec8bab3SRichard Henderson 
7437ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7447ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7457ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7467ec8bab3SRichard Henderson         return;
7477ec8bab3SRichard Henderson     }
7487ec8bab3SRichard Henderson 
7497ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7507ec8bab3SRichard Henderson     switch (ofs + len) {
7517ec8bab3SRichard Henderson     case 16:
7527ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7537ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7547ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7557ec8bab3SRichard Henderson             return;
7567ec8bab3SRichard Henderson         }
7577ec8bab3SRichard Henderson         break;
7587ec8bab3SRichard Henderson     case 8:
7597ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7607ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7617ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7627ec8bab3SRichard Henderson             return;
7637ec8bab3SRichard Henderson         }
7647ec8bab3SRichard Henderson         break;
7657ec8bab3SRichard Henderson     }
7667ec8bab3SRichard Henderson     switch (len) {
7677ec8bab3SRichard Henderson     case 16:
7687ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7697ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7707ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
7717ec8bab3SRichard Henderson             return;
7727ec8bab3SRichard Henderson         }
7737ec8bab3SRichard Henderson         break;
7747ec8bab3SRichard Henderson     case 8:
7757ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7767ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7777ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
7787ec8bab3SRichard Henderson             return;
7797ec8bab3SRichard Henderson         }
7807ec8bab3SRichard Henderson         break;
7817ec8bab3SRichard Henderson     }
7827ec8bab3SRichard Henderson 
7837ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7847ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
7857ec8bab3SRichard Henderson }
7867ec8bab3SRichard Henderson 
7872089fcc9SDavid Hildenbrand /*
7882089fcc9SDavid Hildenbrand  * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
7892089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
7902089fcc9SDavid Hildenbrand  */
7912089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
7922089fcc9SDavid Hildenbrand                           unsigned int ofs)
7932089fcc9SDavid Hildenbrand {
7942089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 32);
7952089fcc9SDavid Hildenbrand     if (ofs == 0) {
7962089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, al);
7972089fcc9SDavid Hildenbrand     } else if (ofs == 32) {
7982089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, ah);
7992089fcc9SDavid Hildenbrand     } else if (al == ah) {
8002089fcc9SDavid Hildenbrand         tcg_gen_rotri_i32(ret, al, ofs);
801fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i32) {
802fce1296fSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
8032089fcc9SDavid Hildenbrand     } else {
8042089fcc9SDavid Hildenbrand         TCGv_i32 t0 = tcg_temp_new_i32();
8052089fcc9SDavid Hildenbrand         tcg_gen_shri_i32(t0, al, ofs);
8062089fcc9SDavid Hildenbrand         tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs);
8072089fcc9SDavid Hildenbrand         tcg_temp_free_i32(t0);
8082089fcc9SDavid Hildenbrand     }
8092089fcc9SDavid Hildenbrand }
8102089fcc9SDavid Hildenbrand 
811951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
812951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
813951c6300SRichard Henderson {
81437ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
81537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
81637ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
81737ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
81837ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
819951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
820951c6300SRichard Henderson     } else {
821951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
822951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
823951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
824951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
825951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
826951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
827951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
828951c6300SRichard Henderson         tcg_temp_free_i32(t0);
829951c6300SRichard Henderson         tcg_temp_free_i32(t1);
830951c6300SRichard Henderson     }
831951c6300SRichard Henderson }
832951c6300SRichard Henderson 
833951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
834951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
835951c6300SRichard Henderson {
836951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
837951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
838951c6300SRichard Henderson     } else {
839951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
840951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
841951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
842951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
843951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
844951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
845951c6300SRichard Henderson         tcg_temp_free_i64(t0);
846951c6300SRichard Henderson         tcg_temp_free_i64(t1);
847951c6300SRichard Henderson     }
848951c6300SRichard Henderson }
849951c6300SRichard Henderson 
850951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
851951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
852951c6300SRichard Henderson {
853951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
854951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
855951c6300SRichard Henderson     } else {
856951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
857951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
858951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
859951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
860951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
861951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
862951c6300SRichard Henderson         tcg_temp_free_i64(t0);
863951c6300SRichard Henderson         tcg_temp_free_i64(t1);
864951c6300SRichard Henderson     }
865951c6300SRichard Henderson }
866951c6300SRichard Henderson 
867951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
868951c6300SRichard Henderson {
869951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
870951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
871951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
872951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
873951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
874951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
875951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
876951c6300SRichard Henderson         tcg_temp_free_i32(t);
8779fd86b51SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
878951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
879951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
880951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
881951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
882951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
883951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
884951c6300SRichard Henderson         tcg_temp_free_i64(t0);
885951c6300SRichard Henderson         tcg_temp_free_i64(t1);
8869fd86b51SRichard Henderson     } else {
8879fd86b51SRichard Henderson         qemu_build_not_reached();
888951c6300SRichard Henderson     }
889951c6300SRichard Henderson }
890951c6300SRichard Henderson 
891951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
892951c6300SRichard Henderson {
893951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
894951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
895951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
896951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
897951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
898951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
899951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
900951c6300SRichard Henderson         tcg_temp_free_i32(t);
901951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
902951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
903951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
904951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
905951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
906951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
907951c6300SRichard Henderson         /* Adjust for negative inputs.  */
908951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
909951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
910951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
911951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
912951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
913951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
914951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
915951c6300SRichard Henderson         tcg_temp_free_i32(t0);
916951c6300SRichard Henderson         tcg_temp_free_i32(t1);
917951c6300SRichard Henderson         tcg_temp_free_i32(t2);
918951c6300SRichard Henderson         tcg_temp_free_i32(t3);
919951c6300SRichard Henderson     } else {
920951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
921951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
922951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
923951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
924951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
925951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
926951c6300SRichard Henderson         tcg_temp_free_i64(t0);
927951c6300SRichard Henderson         tcg_temp_free_i64(t1);
928951c6300SRichard Henderson     }
929951c6300SRichard Henderson }
930951c6300SRichard Henderson 
9315087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9325087abfbSRichard Henderson {
9335087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9345087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9355087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9365087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9375087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9385087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9395087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9405087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9415087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9425087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9435087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9445087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9455087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9465087abfbSRichard Henderson     } else {
9475087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9485087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9495087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9505087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9515087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9525087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9535087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9545087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9555087abfbSRichard Henderson     }
9565087abfbSRichard Henderson }
9575087abfbSRichard Henderson 
958951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
959951c6300SRichard Henderson {
960951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
961951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
962951c6300SRichard Henderson     } else {
963951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
964951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
965951c6300SRichard Henderson     }
966951c6300SRichard Henderson }
967951c6300SRichard Henderson 
968951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
969951c6300SRichard Henderson {
970951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
971951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
972951c6300SRichard Henderson     } else {
973951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
974951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
975951c6300SRichard Henderson     }
976951c6300SRichard Henderson }
977951c6300SRichard Henderson 
978951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
979951c6300SRichard Henderson {
980951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
981951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
982951c6300SRichard Henderson     } else {
983951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
984951c6300SRichard Henderson     }
985951c6300SRichard Henderson }
986951c6300SRichard Henderson 
987951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
988951c6300SRichard Henderson {
989951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
990951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
991951c6300SRichard Henderson     } else {
992951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
993951c6300SRichard Henderson     }
994951c6300SRichard Henderson }
995951c6300SRichard Henderson 
9962b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
997951c6300SRichard Henderson {
9982b836c2aSRichard Henderson     /* Only one extension flag may be present. */
9992b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
10002b836c2aSRichard Henderson 
1001951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
10022b836c2aSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags);
1003951c6300SRichard Henderson     } else {
1004951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
10052b836c2aSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
1006951c6300SRichard Henderson 
10072b836c2aSRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);
10082b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
10092b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t0, t0);
10102b836c2aSRichard Henderson         }
10112b836c2aSRichard Henderson 
10122b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
10132b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 24);
10142b836c2aSRichard Henderson             tcg_gen_sari_i32(t1, t1, 16);
10152b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
10162b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t1, arg);
10172b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, t1, 8);
10182b836c2aSRichard Henderson         } else {
10192b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 8);
10202b836c2aSRichard Henderson         }
10212b836c2aSRichard Henderson 
10222b836c2aSRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1023951c6300SRichard Henderson         tcg_temp_free_i32(t0);
10242b836c2aSRichard Henderson         tcg_temp_free_i32(t1);
1025951c6300SRichard Henderson     }
1026951c6300SRichard Henderson }
1027951c6300SRichard Henderson 
1028951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1029951c6300SRichard Henderson {
1030951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1031587195bdSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
1032951c6300SRichard Henderson     } else {
1033a686dc71SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1034a686dc71SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
103511d11d61SRichard Henderson         TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
1036951c6300SRichard Henderson 
1037a686dc71SRichard Henderson                                         /* arg = abcd */
1038a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);   /*  t0 = .abc */
1039a686dc71SRichard Henderson         tcg_gen_and_i32(t1, arg, t2);   /*  t1 = .b.d */
1040a686dc71SRichard Henderson         tcg_gen_and_i32(t0, t0, t2);    /*  t0 = .a.c */
1041a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = b.d. */
1042a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = badc */
1043951c6300SRichard Henderson 
1044a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, ret, 16);  /*  t0 = ..ba */
1045a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, ret, 16);  /*  t1 = dc.. */
1046a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = dcba */
1047951c6300SRichard Henderson 
1048951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1049951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1050951c6300SRichard Henderson     }
1051951c6300SRichard Henderson }
1052951c6300SRichard Henderson 
105346be8425SRichard Henderson void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg)
105446be8425SRichard Henderson {
105546be8425SRichard Henderson     /* Swapping 2 16-bit elements is a rotate. */
105646be8425SRichard Henderson     tcg_gen_rotli_i32(ret, arg, 16);
105746be8425SRichard Henderson }
105846be8425SRichard Henderson 
1059b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1060b87fb8cdSRichard Henderson {
1061b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1062b87fb8cdSRichard Henderson }
1063b87fb8cdSRichard Henderson 
1064b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1065b87fb8cdSRichard Henderson {
1066b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1067b87fb8cdSRichard Henderson }
1068b87fb8cdSRichard Henderson 
1069b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1070b87fb8cdSRichard Henderson {
1071b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1072b87fb8cdSRichard Henderson }
1073b87fb8cdSRichard Henderson 
1074b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1075b87fb8cdSRichard Henderson {
1076b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1077b87fb8cdSRichard Henderson }
1078b87fb8cdSRichard Henderson 
1079ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
1080ff1f11f7SRichard Henderson {
1081ff1f11f7SRichard Henderson     TCGv_i32 t = tcg_temp_new_i32();
1082ff1f11f7SRichard Henderson 
1083ff1f11f7SRichard Henderson     tcg_gen_sari_i32(t, a, 31);
1084ff1f11f7SRichard Henderson     tcg_gen_xor_i32(ret, a, t);
1085ff1f11f7SRichard Henderson     tcg_gen_sub_i32(ret, ret, t);
1086ff1f11f7SRichard Henderson     tcg_temp_free_i32(t);
1087ff1f11f7SRichard Henderson }
1088ff1f11f7SRichard Henderson 
1089951c6300SRichard Henderson /* 64-bit ops */
1090951c6300SRichard Henderson 
1091951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1092951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1093951c6300SRichard Henderson 
1094951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1095951c6300SRichard Henderson {
1096951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1097951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1098951c6300SRichard Henderson }
1099951c6300SRichard Henderson 
1100951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1101951c6300SRichard Henderson {
110211d11d61SRichard Henderson     TCGTemp *ts = tcgv_i64_temp(arg);
110311d11d61SRichard Henderson 
110411d11d61SRichard Henderson     /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
110511d11d61SRichard Henderson     if (ts->kind == TEMP_CONST) {
110611d11d61SRichard Henderson         tcg_gen_movi_i64(ret, ts->val);
110711d11d61SRichard Henderson     } else {
1108951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1109951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1110951c6300SRichard Henderson     }
111111d11d61SRichard Henderson }
1112951c6300SRichard Henderson 
1113951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1114951c6300SRichard Henderson {
1115951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1116951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1117951c6300SRichard Henderson }
1118951c6300SRichard Henderson 
1119951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1120951c6300SRichard Henderson {
1121951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1122951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1123951c6300SRichard Henderson }
1124951c6300SRichard Henderson 
1125951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1126951c6300SRichard Henderson {
1127951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11283ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1129951c6300SRichard Henderson }
1130951c6300SRichard Henderson 
1131951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1132951c6300SRichard Henderson {
1133951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1134951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1135951c6300SRichard Henderson }
1136951c6300SRichard Henderson 
1137951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1138951c6300SRichard Henderson {
1139951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1140951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1141951c6300SRichard Henderson }
1142951c6300SRichard Henderson 
1143951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1144951c6300SRichard Henderson {
1145951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1146951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1147951c6300SRichard Henderson }
1148951c6300SRichard Henderson 
1149951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1150951c6300SRichard Henderson {
1151951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1152951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1153951c6300SRichard Henderson }
1154951c6300SRichard Henderson 
1155951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1156951c6300SRichard Henderson {
1157951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1158951c6300SRichard Henderson        they cannot be the same temporary */
1159e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1160951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1161951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1162951c6300SRichard Henderson #else
1163951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1164951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1165951c6300SRichard Henderson #endif
1166951c6300SRichard Henderson }
1167951c6300SRichard Henderson 
1168d56fea79SRichard Henderson void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1169d56fea79SRichard Henderson {
1170d56fea79SRichard Henderson     tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset);
1171d56fea79SRichard Henderson }
1172d56fea79SRichard Henderson 
1173d56fea79SRichard Henderson void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1174d56fea79SRichard Henderson {
1175d56fea79SRichard Henderson     tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset);
1176d56fea79SRichard Henderson }
1177d56fea79SRichard Henderson 
1178d56fea79SRichard Henderson void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1179d56fea79SRichard Henderson {
1180d56fea79SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1181d56fea79SRichard Henderson }
1182d56fea79SRichard Henderson 
1183951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1184951c6300SRichard Henderson {
1185e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1186951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1187951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1188951c6300SRichard Henderson #else
1189951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1190951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1191951c6300SRichard Henderson #endif
1192951c6300SRichard Henderson }
1193951c6300SRichard Henderson 
1194d56fea79SRichard Henderson void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1195d56fea79SRichard Henderson {
1196d56fea79SRichard Henderson     tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1),
1197d56fea79SRichard Henderson                      TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2));
1198d56fea79SRichard Henderson }
1199d56fea79SRichard Henderson 
1200d56fea79SRichard Henderson void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1201d56fea79SRichard Henderson {
1202d56fea79SRichard Henderson     tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1),
1203d56fea79SRichard Henderson                      TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2));
1204d56fea79SRichard Henderson }
1205d56fea79SRichard Henderson 
1206951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1207951c6300SRichard Henderson {
1208951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1209951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1210951c6300SRichard Henderson }
1211951c6300SRichard Henderson 
1212951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1213951c6300SRichard Henderson {
1214951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1215951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1216951c6300SRichard Henderson }
1217951c6300SRichard Henderson 
1218951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1219951c6300SRichard Henderson {
1220951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1221951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1222951c6300SRichard Henderson }
1223951c6300SRichard Henderson 
1224951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1225951c6300SRichard Henderson {
1226951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1227951c6300SRichard Henderson }
1228951c6300SRichard Henderson 
1229951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1230951c6300SRichard Henderson {
1231951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1232951c6300SRichard Henderson }
1233951c6300SRichard Henderson 
1234951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1235951c6300SRichard Henderson {
1236951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1237951c6300SRichard Henderson }
1238951c6300SRichard Henderson 
1239951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1240951c6300SRichard Henderson {
1241951c6300SRichard Henderson     TCGv_i64 t0;
1242951c6300SRichard Henderson     TCGv_i32 t1;
1243951c6300SRichard Henderson 
1244951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1245951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1246951c6300SRichard Henderson 
1247951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1248951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1249951c6300SRichard Henderson 
1250951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1251951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1252951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1253951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1254951c6300SRichard Henderson 
1255951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1256951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1257951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1258951c6300SRichard Henderson }
125911d11d61SRichard Henderson 
126011d11d61SRichard Henderson #else
126111d11d61SRichard Henderson 
126211d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
126311d11d61SRichard Henderson {
126411d11d61SRichard Henderson     tcg_gen_mov_i64(ret, tcg_constant_i64(arg));
126511d11d61SRichard Henderson }
126611d11d61SRichard Henderson 
1267951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1268951c6300SRichard Henderson 
1269951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1270951c6300SRichard Henderson {
1271951c6300SRichard Henderson     /* some cases can be optimized here */
1272951c6300SRichard Henderson     if (arg2 == 0) {
1273951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
127411d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
127511d11d61SRichard Henderson         tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2));
1276951c6300SRichard Henderson     } else {
127711d11d61SRichard Henderson         tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
127811d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
127911d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1280951c6300SRichard Henderson     }
1281951c6300SRichard Henderson }
1282951c6300SRichard Henderson 
1283951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1284951c6300SRichard Henderson {
1285951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1286951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1287951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
128811d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
128911d11d61SRichard Henderson         tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
1290951c6300SRichard Henderson     } else {
129111d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
129211d11d61SRichard Henderson                          tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32),
129311d11d61SRichard Henderson                          TCGV_LOW(arg2), TCGV_HIGH(arg2));
1294951c6300SRichard Henderson     }
1295951c6300SRichard Henderson }
1296951c6300SRichard Henderson 
1297951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1298951c6300SRichard Henderson {
1299951c6300SRichard Henderson     /* some cases can be optimized here */
1300951c6300SRichard Henderson     if (arg2 == 0) {
1301951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
130211d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
130311d11d61SRichard Henderson         tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2));
1304951c6300SRichard Henderson     } else {
130511d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
130611d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
130711d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1308951c6300SRichard Henderson     }
1309951c6300SRichard Henderson }
1310951c6300SRichard Henderson 
1311474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1312951c6300SRichard Henderson {
13133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1314951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1315951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13163a13c3f3SRichard Henderson         return;
13173a13c3f3SRichard Henderson     }
13183a13c3f3SRichard Henderson 
1319951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1320951c6300SRichard Henderson     switch (arg2) {
1321951c6300SRichard Henderson     case 0:
1322951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1323951c6300SRichard Henderson         return;
1324474b2e8fSRichard Henderson     case -1:
1325951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1326951c6300SRichard Henderson         return;
1327474b2e8fSRichard Henderson     case 0xff:
1328951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1329951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1330951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1331951c6300SRichard Henderson             return;
1332951c6300SRichard Henderson         }
1333951c6300SRichard Henderson         break;
1334474b2e8fSRichard Henderson     case 0xffff:
1335951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1336951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1337951c6300SRichard Henderson             return;
1338951c6300SRichard Henderson         }
1339951c6300SRichard Henderson         break;
1340474b2e8fSRichard Henderson     case 0xffffffffu:
1341951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1342951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1343951c6300SRichard Henderson             return;
1344951c6300SRichard Henderson         }
1345951c6300SRichard Henderson         break;
1346951c6300SRichard Henderson     }
134711d11d61SRichard Henderson 
134811d11d61SRichard Henderson     tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2));
1349951c6300SRichard Henderson }
1350951c6300SRichard Henderson 
1351951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1352951c6300SRichard Henderson {
13533a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1354951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1355951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13563a13c3f3SRichard Henderson         return;
13573a13c3f3SRichard Henderson     }
1358951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1359951c6300SRichard Henderson     if (arg2 == -1) {
1360951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1361951c6300SRichard Henderson     } else if (arg2 == 0) {
1362951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1363951c6300SRichard Henderson     } else {
136411d11d61SRichard Henderson         tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2));
1365951c6300SRichard Henderson     }
1366951c6300SRichard Henderson }
1367951c6300SRichard Henderson 
1368951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1369951c6300SRichard Henderson {
13703a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1371951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1372951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13733a13c3f3SRichard Henderson         return;
13743a13c3f3SRichard Henderson     }
1375951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1376951c6300SRichard Henderson     if (arg2 == 0) {
1377951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1378951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1379951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1380951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1381951c6300SRichard Henderson     } else {
138211d11d61SRichard Henderson         tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2));
1383951c6300SRichard Henderson     }
1384951c6300SRichard Henderson }
1385951c6300SRichard Henderson 
1386951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1387951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1388951c6300SRichard Henderson {
1389951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1390951c6300SRichard Henderson     if (c == 0) {
1391951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1392951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1393951c6300SRichard Henderson     } else if (c >= 32) {
1394951c6300SRichard Henderson         c -= 32;
1395951c6300SRichard Henderson         if (right) {
1396951c6300SRichard Henderson             if (arith) {
1397951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1398951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1399951c6300SRichard Henderson             } else {
1400951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1401951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1402951c6300SRichard Henderson             }
1403951c6300SRichard Henderson         } else {
1404951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1405951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1406951c6300SRichard Henderson         }
140702616badSRichard Henderson     } else if (right) {
140802616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
140902616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_LOW(ret),
141002616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1411951c6300SRichard Henderson         } else {
1412951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
141302616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret),
141402616badSRichard Henderson                                 TCGV_HIGH(arg1), 32 - c, c);
1415951c6300SRichard Henderson         }
141602616badSRichard Henderson         if (arith) {
141702616badSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
141802616badSRichard Henderson         } else {
141902616badSRichard Henderson             tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
142002616badSRichard Henderson         }
142102616badSRichard Henderson     } else {
142202616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
142302616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_HIGH(ret),
142402616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
142502616badSRichard Henderson         } else {
142602616badSRichard Henderson             TCGv_i32 t0 = tcg_temp_new_i32();
142702616badSRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
142802616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), t0,
142902616badSRichard Henderson                                 TCGV_HIGH(arg1), c, 32 - c);
1430951c6300SRichard Henderson             tcg_temp_free_i32(t0);
143102616badSRichard Henderson         }
143202616badSRichard Henderson         tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1433951c6300SRichard Henderson     }
1434951c6300SRichard Henderson }
1435951c6300SRichard Henderson 
1436474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1437951c6300SRichard Henderson {
1438474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14393a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14403a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
14413a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1442951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1443951c6300SRichard Henderson     } else {
144411d11d61SRichard Henderson         tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2));
1445951c6300SRichard Henderson     }
1446951c6300SRichard Henderson }
1447951c6300SRichard Henderson 
1448474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1449951c6300SRichard Henderson {
1450474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14513a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14523a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
14533a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1454951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1455951c6300SRichard Henderson     } else {
145611d11d61SRichard Henderson         tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2));
1457951c6300SRichard Henderson     }
1458951c6300SRichard Henderson }
1459951c6300SRichard Henderson 
1460474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1461951c6300SRichard Henderson {
1462474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14633a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14643a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
14653a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1466951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1467951c6300SRichard Henderson     } else {
146811d11d61SRichard Henderson         tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2));
1469951c6300SRichard Henderson     }
1470951c6300SRichard Henderson }
1471951c6300SRichard Henderson 
147242a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1473951c6300SRichard Henderson {
1474951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
147542a268c2SRichard Henderson         tcg_gen_br(l);
1476951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1477d88a117eSRichard Henderson         l->refs++;
14783a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1479951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1480951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
148142a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14823a13c3f3SRichard Henderson         } else {
148342a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
148442a268c2SRichard Henderson                               label_arg(l));
14853a13c3f3SRichard Henderson         }
1486951c6300SRichard Henderson     }
1487951c6300SRichard Henderson }
1488951c6300SRichard Henderson 
148942a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1490951c6300SRichard Henderson {
149111d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
149211d11d61SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l);
149311d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
149442a268c2SRichard Henderson         tcg_gen_br(l);
1495951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
149611d11d61SRichard Henderson         l->refs++;
149711d11d61SRichard Henderson         tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
149811d11d61SRichard Henderson                           TCGV_LOW(arg1), TCGV_HIGH(arg1),
149911d11d61SRichard Henderson                           tcg_constant_i32(arg2),
150011d11d61SRichard Henderson                           tcg_constant_i32(arg2 >> 32),
150111d11d61SRichard Henderson                           cond, label_arg(l));
1502951c6300SRichard Henderson     }
1503951c6300SRichard Henderson }
1504951c6300SRichard Henderson 
1505951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1506951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1507951c6300SRichard Henderson {
1508951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1509951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1510951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1511951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1512951c6300SRichard Henderson     } else {
15133a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1514951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1515951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1516951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1517951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15183a13c3f3SRichard Henderson         } else {
1519951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
15203a13c3f3SRichard Henderson         }
1521951c6300SRichard Henderson     }
1522951c6300SRichard Henderson }
1523951c6300SRichard Henderson 
1524951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1525951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1526951c6300SRichard Henderson {
152711d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
152811d11d61SRichard Henderson         tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2));
152911d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
153011d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 1);
153111d11d61SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
153211d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 0);
153311d11d61SRichard Henderson     } else {
153411d11d61SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
153511d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
153611d11d61SRichard Henderson                          tcg_constant_i32(arg2),
153711d11d61SRichard Henderson                          tcg_constant_i32(arg2 >> 32), cond);
153811d11d61SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
153911d11d61SRichard Henderson     }
1540951c6300SRichard Henderson }
1541951c6300SRichard Henderson 
1542951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1543951c6300SRichard Henderson {
1544b2e3ae94SRichard Henderson     if (arg2 == 0) {
1545b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1546b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1547b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1548b2e3ae94SRichard Henderson     } else {
1549951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1550951c6300SRichard Henderson         tcg_gen_mul_i64(ret, arg1, t0);
1551951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1552951c6300SRichard Henderson     }
1553b2e3ae94SRichard Henderson }
1554951c6300SRichard Henderson 
1555951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1556951c6300SRichard Henderson {
1557951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1558951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1559951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1560951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1561951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1562951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1563951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1564951c6300SRichard Henderson     } else {
1565951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1566951c6300SRichard Henderson     }
1567951c6300SRichard Henderson }
1568951c6300SRichard Henderson 
1569951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1570951c6300SRichard Henderson {
1571951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1572951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1573951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1574951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1575951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1576951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1577951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1578951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1579951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1580951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1581951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1582951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1583951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1584951c6300SRichard Henderson     } else {
1585951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1586951c6300SRichard Henderson     }
1587951c6300SRichard Henderson }
1588951c6300SRichard Henderson 
1589951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1590951c6300SRichard Henderson {
1591951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1592951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1593951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1594951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1595951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1596951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1597951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1598951c6300SRichard Henderson     } else {
1599951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1600951c6300SRichard Henderson     }
1601951c6300SRichard Henderson }
1602951c6300SRichard Henderson 
1603951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1604951c6300SRichard Henderson {
1605951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1606951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1607951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1608951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1609951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1610951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1611951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1612951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1613951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1614951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1615951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1616951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1617951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1618951c6300SRichard Henderson     } else {
1619951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1620951c6300SRichard Henderson     }
1621951c6300SRichard Henderson }
1622951c6300SRichard Henderson 
1623951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1624951c6300SRichard Henderson {
16253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1626951c6300SRichard Henderson         tcg_gen_ext8s_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_ext8s_i64) {
1629951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1630951c6300SRichard Henderson     } else {
1631951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1632951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1633951c6300SRichard Henderson     }
1634951c6300SRichard Henderson }
1635951c6300SRichard Henderson 
1636951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1637951c6300SRichard Henderson {
16383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1639951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1640951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16413a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1642951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1643951c6300SRichard Henderson     } else {
1644951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1645951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1646951c6300SRichard Henderson     }
1647951c6300SRichard Henderson }
1648951c6300SRichard Henderson 
1649951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1650951c6300SRichard Henderson {
16513a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1652951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1653951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1655951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1656951c6300SRichard Henderson     } else {
1657951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1658951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1659951c6300SRichard Henderson     }
1660951c6300SRichard Henderson }
1661951c6300SRichard Henderson 
1662951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1663951c6300SRichard Henderson {
16643a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1665951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1666951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16673a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1668951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1669951c6300SRichard Henderson     } else {
1670951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1671951c6300SRichard Henderson     }
1672951c6300SRichard Henderson }
1673951c6300SRichard Henderson 
1674951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1675951c6300SRichard Henderson {
16763a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1677951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1678951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16793a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1680951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1681951c6300SRichard Henderson     } else {
1682951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1683951c6300SRichard Henderson     }
1684951c6300SRichard Henderson }
1685951c6300SRichard Henderson 
1686951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1687951c6300SRichard Henderson {
16883a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1689951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1690951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16913a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1692951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1693951c6300SRichard Henderson     } else {
1694951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1695951c6300SRichard Henderson     }
1696951c6300SRichard Henderson }
1697951c6300SRichard Henderson 
16982b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1699951c6300SRichard Henderson {
17002b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17012b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17022b836c2aSRichard Henderson 
17033a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17042b836c2aSRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags);
17052b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17062b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17072b836c2aSRichard Henderson         } else {
1708951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17092b836c2aSRichard Henderson         }
17103a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
17112b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags);
1712951c6300SRichard Henderson     } else {
1713951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
17142b836c2aSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1715951c6300SRichard Henderson 
17162b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);
17172b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
17182b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t0, t0);
17192b836c2aSRichard Henderson         }
17202b836c2aSRichard Henderson 
17212b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17222b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 56);
17232b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 48);
17242b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
17252b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t1, arg);
17262b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, t1, 8);
17272b836c2aSRichard Henderson         } else {
17282b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 8);
17292b836c2aSRichard Henderson         }
17302b836c2aSRichard Henderson 
17312b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1732951c6300SRichard Henderson         tcg_temp_free_i64(t0);
17332b836c2aSRichard Henderson         tcg_temp_free_i64(t1);
1734951c6300SRichard Henderson     }
1735951c6300SRichard Henderson }
1736951c6300SRichard Henderson 
17372b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1738951c6300SRichard Henderson {
17392b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17402b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17412b836c2aSRichard Henderson 
17423a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1743951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17442b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17452b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17462b836c2aSRichard Henderson         } else {
1747951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17482b836c2aSRichard Henderson         }
17493a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
17502b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags);
1751951c6300SRichard Henderson     } else {
1752a686dc71SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1753a686dc71SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
175411d11d61SRichard Henderson         TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
1755951c6300SRichard Henderson 
17562b836c2aSRichard Henderson                                             /* arg = xxxxabcd */
17572b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);       /*  t0 = .xxxxabc */
1758a686dc71SRichard Henderson         tcg_gen_and_i64(t1, arg, t2);       /*  t1 = .....b.d */
1759a686dc71SRichard Henderson         tcg_gen_and_i64(t0, t0, t2);        /*  t0 = .....a.c */
1760a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);        /*  t1 = ....b.d. */
1761a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ....badc */
1762951c6300SRichard Henderson 
1763a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, ret, 48);      /*  t1 = dc...... */
1764a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);      /*  t0 = ......ba */
17652b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17662b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 32);   /*  t1 = ssssdc.. */
17672b836c2aSRichard Henderson         } else {
1768a686dc71SRichard Henderson             tcg_gen_shri_i64(t1, t1, 32);   /*  t1 = ....dc.. */
17692b836c2aSRichard Henderson         }
17702b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ssssdcba */
1771951c6300SRichard Henderson 
1772951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1773951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1774951c6300SRichard Henderson     }
1775951c6300SRichard Henderson }
1776951c6300SRichard Henderson 
1777951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1778951c6300SRichard Henderson {
17793a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1780951c6300SRichard Henderson         TCGv_i32 t0, t1;
1781951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1782951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1783951c6300SRichard Henderson 
1784951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1785951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1786951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1787951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1788951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1789951c6300SRichard Henderson         tcg_temp_free_i32(t1);
17903a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1791587195bdSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
1792951c6300SRichard Henderson     } else {
1793951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1794951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
17959e821eabSRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
1796951c6300SRichard Henderson 
17979e821eabSRichard Henderson                                         /* arg = abcdefgh */
17989e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
17999e821eabSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .abcdefg */
18009e821eabSRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .b.d.f.h */
18019e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .a.c.e.g */
18029e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = b.d.f.h. */
18039e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = badcfehg */
1804951c6300SRichard Henderson 
18059e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
18069e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ..badcfe */
18079e821eabSRichard Henderson         tcg_gen_and_i64(t1, ret, t2);   /*  t1 = ..dc..hg */
18089e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = ..ba..fe */
18099e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 16);   /*  t1 = dc..hg.. */
18109e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = dcbahgfe */
1811951c6300SRichard Henderson 
18129e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 32);  /*  t0 = ....dcba */
18139e821eabSRichard Henderson         tcg_gen_shli_i64(t1, ret, 32);  /*  t1 = hgfe.... */
18149e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = hgfedcba */
1815951c6300SRichard Henderson 
1816951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1817951c6300SRichard Henderson         tcg_temp_free_i64(t1);
18189e821eabSRichard Henderson         tcg_temp_free_i64(t2);
1819951c6300SRichard Henderson     }
1820951c6300SRichard Henderson }
1821951c6300SRichard Henderson 
182246be8425SRichard Henderson void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg)
182346be8425SRichard Henderson {
182446be8425SRichard Henderson     uint64_t m = 0x0000ffff0000ffffull;
182546be8425SRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
182646be8425SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
182746be8425SRichard Henderson 
182846be8425SRichard Henderson     /* See include/qemu/bitops.h, hswap64. */
182946be8425SRichard Henderson     tcg_gen_rotli_i64(t1, arg, 32);
183046be8425SRichard Henderson     tcg_gen_andi_i64(t0, t1, m);
183146be8425SRichard Henderson     tcg_gen_shli_i64(t0, t0, 16);
183246be8425SRichard Henderson     tcg_gen_shri_i64(t1, t1, 16);
183346be8425SRichard Henderson     tcg_gen_andi_i64(t1, t1, m);
183446be8425SRichard Henderson     tcg_gen_or_i64(ret, t0, t1);
183546be8425SRichard Henderson 
183646be8425SRichard Henderson     tcg_temp_free_i64(t0);
183746be8425SRichard Henderson     tcg_temp_free_i64(t1);
183846be8425SRichard Henderson }
183946be8425SRichard Henderson 
184046be8425SRichard Henderson void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg)
184146be8425SRichard Henderson {
184246be8425SRichard Henderson     /* Swapping 2 32-bit elements is a rotate. */
184346be8425SRichard Henderson     tcg_gen_rotli_i64(ret, arg, 32);
184446be8425SRichard Henderson }
184546be8425SRichard Henderson 
1846951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1847951c6300SRichard Henderson {
18483a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18493a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
18503a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
18513a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1852951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1853951c6300SRichard Henderson     } else {
1854951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1855951c6300SRichard Henderson     }
1856951c6300SRichard Henderson }
1857951c6300SRichard Henderson 
1858951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1859951c6300SRichard Henderson {
18603a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18613a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18623a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18633a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1864951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1865951c6300SRichard Henderson     } else {
1866951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1867951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1868951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1869951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1870951c6300SRichard Henderson     }
1871951c6300SRichard Henderson }
1872951c6300SRichard Henderson 
1873951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1874951c6300SRichard Henderson {
18753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18763a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18773a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18783a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1879951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1880951c6300SRichard Henderson     } else {
1881951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1882951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1883951c6300SRichard Henderson     }
1884951c6300SRichard Henderson }
1885951c6300SRichard Henderson 
1886951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1887951c6300SRichard Henderson {
18883a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18893a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18903a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18913a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1892951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1893951c6300SRichard Henderson     } else {
1894951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1895951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1896951c6300SRichard Henderson     }
1897951c6300SRichard Henderson }
1898951c6300SRichard Henderson 
1899951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1900951c6300SRichard Henderson {
19013a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19023a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19033a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19043a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1905951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1906951c6300SRichard Henderson     } else {
1907951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1908951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1909951c6300SRichard Henderson     }
1910951c6300SRichard Henderson }
1911951c6300SRichard Henderson 
1912951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1913951c6300SRichard Henderson {
19143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
19153a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
19163a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
19173a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1918951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1919951c6300SRichard Henderson     } else {
1920951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1921951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1922951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1923951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1924951c6300SRichard Henderson     }
1925951c6300SRichard Henderson }
1926951c6300SRichard Henderson 
19270e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
19280e28d006SRichard Henderson {
19290e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
19300e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
19310e28d006SRichard Henderson     } else {
19320e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
19330e28d006SRichard Henderson     }
19340e28d006SRichard Henderson }
19350e28d006SRichard Henderson 
19360e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
19370e28d006SRichard Henderson {
19380e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
19390e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
19400e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
194111d11d61SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
194211d11d61SRichard Henderson         tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32);
19430e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
19440e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
19450e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
19460e28d006SRichard Henderson         tcg_temp_free_i32(t);
19470e28d006SRichard Henderson     } else {
194811d11d61SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
194911d11d61SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t0);
195011d11d61SRichard Henderson         tcg_temp_free_i64(t0);
19510e28d006SRichard Henderson     }
19520e28d006SRichard Henderson }
19530e28d006SRichard Henderson 
19540e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
19550e28d006SRichard Henderson {
19560e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
19570e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
195814e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
195914e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
196014e99210SRichard Henderson 
196114e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
196214e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
196314e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
196414e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
196514e99210SRichard Henderson         } else {
196614e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
196714e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
196814e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
196914e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
197014e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
197114e99210SRichard Henderson         }
197211d11d61SRichard Henderson         z = tcg_constant_i64(0);
197314e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
197414e99210SRichard Henderson         tcg_temp_free_i64(t);
197514e99210SRichard Henderson         tcg_temp_free_i64(z);
19760e28d006SRichard Henderson     } else {
19770e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
19780e28d006SRichard Henderson     }
19790e28d006SRichard Henderson }
19800e28d006SRichard Henderson 
19810e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
19820e28d006SRichard Henderson {
19830e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
19840e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
19850e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
198611d11d61SRichard Henderson         TCGv_i32 t32 = tcg_temp_new_i32();
198711d11d61SRichard Henderson         tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32);
19880e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
19890e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
19900e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
19910e28d006SRichard Henderson         tcg_temp_free_i32(t32);
199214e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
199314e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
199414e99210SRichard Henderson                && arg2 == 64) {
199514e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
199614e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
199714e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
199814e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
199914e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
200014e99210SRichard Henderson         tcg_temp_free_i64(t);
20010e28d006SRichard Henderson     } else {
200211d11d61SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
200311d11d61SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t0);
200411d11d61SRichard Henderson         tcg_temp_free_i64(t0);
20050e28d006SRichard Henderson     }
20060e28d006SRichard Henderson }
20070e28d006SRichard Henderson 
2008086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
2009086920c2SRichard Henderson {
2010086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
2011086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2012086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
2013086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
2014086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
2015086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
2016086920c2SRichard Henderson         tcg_temp_free_i64(t);
2017086920c2SRichard Henderson     } else {
2018086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
2019086920c2SRichard Henderson     }
2020086920c2SRichard Henderson }
2021086920c2SRichard Henderson 
2022a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
2023a768e4e9SRichard Henderson {
2024a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
2025a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
2026a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
2027a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2028a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2029a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
2030a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
2031a768e4e9SRichard Henderson     } else {
2032a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
2033a768e4e9SRichard Henderson     }
2034a768e4e9SRichard Henderson }
2035a768e4e9SRichard Henderson 
2036951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2037951c6300SRichard Henderson {
2038951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2039951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
2040951c6300SRichard Henderson     } else {
2041951c6300SRichard Henderson         TCGv_i64 t0, t1;
2042951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2043951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2044951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
2045951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2046951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
2047951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2048951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2049951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2050951c6300SRichard Henderson     }
2051951c6300SRichard Henderson }
2052951c6300SRichard Henderson 
205307dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2054951c6300SRichard Henderson {
205507dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2056951c6300SRichard Henderson     /* some cases can be optimized here */
2057951c6300SRichard Henderson     if (arg2 == 0) {
2058951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2059951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
206011d11d61SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2));
2061951c6300SRichard Henderson     } else {
2062951c6300SRichard Henderson         TCGv_i64 t0, t1;
2063951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2064951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2065951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
2066951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
2067951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2068951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2069951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2070951c6300SRichard Henderson     }
2071951c6300SRichard Henderson }
2072951c6300SRichard Henderson 
2073951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2074951c6300SRichard Henderson {
2075951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2076951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
2077951c6300SRichard Henderson     } else {
2078951c6300SRichard Henderson         TCGv_i64 t0, t1;
2079951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2080951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2081951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
2082951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2083951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
2084951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2085951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2086951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2087951c6300SRichard Henderson     }
2088951c6300SRichard Henderson }
2089951c6300SRichard Henderson 
209007dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2091951c6300SRichard Henderson {
209207dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2093951c6300SRichard Henderson     /* some cases can be optimized here */
2094951c6300SRichard Henderson     if (arg2 == 0) {
2095951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2096951c6300SRichard Henderson     } else {
2097951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
2098951c6300SRichard Henderson     }
2099951c6300SRichard Henderson }
2100951c6300SRichard Henderson 
2101951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
2102951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
2103951c6300SRichard Henderson {
2104951c6300SRichard Henderson     uint64_t mask;
2105951c6300SRichard Henderson     TCGv_i64 t1;
2106951c6300SRichard Henderson 
2107951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
21080d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2109951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2110951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2111951c6300SRichard Henderson 
21120d0d309dSRichard Henderson     if (len == 64) {
2113951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2114951c6300SRichard Henderson         return;
2115951c6300SRichard Henderson     }
2116951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2117951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2118951c6300SRichard Henderson         return;
2119951c6300SRichard Henderson     }
2120951c6300SRichard Henderson 
21213a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2122951c6300SRichard Henderson         if (ofs >= 32) {
2123951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2124951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2125951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2126951c6300SRichard Henderson             return;
2127951c6300SRichard Henderson         }
2128951c6300SRichard Henderson         if (ofs + len <= 32) {
2129951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2130951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2131951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2132951c6300SRichard Henderson             return;
2133951c6300SRichard Henderson         }
21343a13c3f3SRichard Henderson     }
2135951c6300SRichard Henderson 
2136951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2137951c6300SRichard Henderson 
2138b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i64) {
2139b0a60567SRichard Henderson         if (ofs + len == 64) {
2140b0a60567SRichard Henderson             tcg_gen_shli_i64(t1, arg1, len);
2141b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, t1, arg2, len);
2142b0a60567SRichard Henderson             goto done;
2143b0a60567SRichard Henderson         }
2144b0a60567SRichard Henderson         if (ofs == 0) {
2145b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, arg1, arg2, len);
2146b0a60567SRichard Henderson             tcg_gen_rotli_i64(ret, ret, len);
2147b0a60567SRichard Henderson             goto done;
2148b0a60567SRichard Henderson         }
2149b0a60567SRichard Henderson     }
2150b0a60567SRichard Henderson 
2151b0a60567SRichard Henderson     mask = (1ull << len) - 1;
2152951c6300SRichard Henderson     if (ofs + len < 64) {
2153951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2154951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2155951c6300SRichard Henderson     } else {
2156951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2157951c6300SRichard Henderson     }
2158951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2159951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2160b0a60567SRichard Henderson  done:
2161951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2162951c6300SRichard Henderson }
2163951c6300SRichard Henderson 
216407cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
216507cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
216607cc68d5SRichard Henderson {
216707cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
216807cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
216907cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
217007cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
217107cc68d5SRichard Henderson 
217207cc68d5SRichard Henderson     if (ofs + len == 64) {
217307cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
217407cc68d5SRichard Henderson     } else if (ofs == 0) {
217507cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
217607cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
217707cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
217811d11d61SRichard Henderson         TCGv_i64 zero = tcg_constant_i64(0);
217907cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
218007cc68d5SRichard Henderson     } else {
218107cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
218207cc68d5SRichard Henderson             if (ofs >= 32) {
218307cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
218407cc68d5SRichard Henderson                                       ofs - 32, len);
218507cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
218607cc68d5SRichard Henderson                 return;
218707cc68d5SRichard Henderson             }
218807cc68d5SRichard Henderson             if (ofs + len <= 32) {
218907cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
219007cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
219107cc68d5SRichard Henderson                 return;
219207cc68d5SRichard Henderson             }
219307cc68d5SRichard Henderson         }
219407cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
219507cc68d5SRichard Henderson            which allows ARG to stay live.  */
219607cc68d5SRichard Henderson         switch (len) {
219707cc68d5SRichard Henderson         case 32:
219807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
219907cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
220007cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
220107cc68d5SRichard Henderson                 return;
220207cc68d5SRichard Henderson             }
220307cc68d5SRichard Henderson             break;
220407cc68d5SRichard Henderson         case 16:
220507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
220607cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
220707cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
220807cc68d5SRichard Henderson                 return;
220907cc68d5SRichard Henderson             }
221007cc68d5SRichard Henderson             break;
221107cc68d5SRichard Henderson         case 8:
221207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
221307cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
221407cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
221507cc68d5SRichard Henderson                 return;
221607cc68d5SRichard Henderson             }
221707cc68d5SRichard Henderson             break;
221807cc68d5SRichard Henderson         }
221907cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
222007cc68d5SRichard Henderson         switch (ofs + len) {
222107cc68d5SRichard Henderson         case 32:
222207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
222307cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
222407cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
222507cc68d5SRichard Henderson                 return;
222607cc68d5SRichard Henderson             }
222707cc68d5SRichard Henderson             break;
222807cc68d5SRichard Henderson         case 16:
222907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
223007cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
223107cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
223207cc68d5SRichard Henderson                 return;
223307cc68d5SRichard Henderson             }
223407cc68d5SRichard Henderson             break;
223507cc68d5SRichard Henderson         case 8:
223607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
223707cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
223807cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
223907cc68d5SRichard Henderson                 return;
224007cc68d5SRichard Henderson             }
224107cc68d5SRichard Henderson             break;
224207cc68d5SRichard Henderson         }
224307cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
224407cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
224507cc68d5SRichard Henderson     }
224607cc68d5SRichard Henderson }
224707cc68d5SRichard Henderson 
22487ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
22497ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
22507ec8bab3SRichard Henderson {
22517ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22527ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22537ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22547ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22557ec8bab3SRichard Henderson 
22567ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
22577ec8bab3SRichard Henderson     if (ofs + len == 64) {
22587ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
22597ec8bab3SRichard Henderson         return;
22607ec8bab3SRichard Henderson     }
22617ec8bab3SRichard Henderson     if (ofs == 0) {
22627ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
22637ec8bab3SRichard Henderson         return;
22647ec8bab3SRichard Henderson     }
22657ec8bab3SRichard Henderson 
22667ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22677ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22687ec8bab3SRichard Henderson         if (ofs >= 32) {
22697ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22707ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22717ec8bab3SRichard Henderson             return;
22727ec8bab3SRichard Henderson         }
22737ec8bab3SRichard Henderson         if (ofs + len <= 32) {
22747ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22757ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22767ec8bab3SRichard Henderson             return;
22777ec8bab3SRichard Henderson         }
22787ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
22797ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
22807ec8bab3SRichard Henderson         goto do_shift_and;
22817ec8bab3SRichard Henderson     }
22827ec8bab3SRichard Henderson 
22837ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
22847ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22857ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
22867ec8bab3SRichard Henderson         return;
22877ec8bab3SRichard Henderson     }
22887ec8bab3SRichard Henderson 
22897ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
22907ec8bab3SRichard Henderson     switch (ofs + len) {
22917ec8bab3SRichard Henderson     case 32:
22927ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
22937ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
22947ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22957ec8bab3SRichard Henderson             return;
22967ec8bab3SRichard Henderson         }
22977ec8bab3SRichard Henderson         break;
22987ec8bab3SRichard Henderson     case 16:
22997ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
23007ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
23017ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
23027ec8bab3SRichard Henderson             return;
23037ec8bab3SRichard Henderson         }
23047ec8bab3SRichard Henderson         break;
23057ec8bab3SRichard Henderson     case 8:
23067ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
23077ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
23087ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
23097ec8bab3SRichard Henderson             return;
23107ec8bab3SRichard Henderson         }
23117ec8bab3SRichard Henderson         break;
23127ec8bab3SRichard Henderson     }
23137ec8bab3SRichard Henderson 
23147ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
23157ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
23167ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
23177ec8bab3SRichard Henderson     switch (len) {
23187ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
23197ec8bab3SRichard Henderson     do_shift_and:
23207ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
23217ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
23227ec8bab3SRichard Henderson         break;
23237ec8bab3SRichard Henderson     default:
23247ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23257ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
23267ec8bab3SRichard Henderson         break;
23277ec8bab3SRichard Henderson     }
23287ec8bab3SRichard Henderson }
23297ec8bab3SRichard Henderson 
23307ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
23317ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
23327ec8bab3SRichard Henderson {
23337ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
23347ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
23357ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
23367ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
23377ec8bab3SRichard Henderson 
23387ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
23397ec8bab3SRichard Henderson     if (ofs + len == 64) {
23407ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
23417ec8bab3SRichard Henderson         return;
23427ec8bab3SRichard Henderson     }
23437ec8bab3SRichard Henderson     if (ofs == 0) {
23447ec8bab3SRichard Henderson         switch (len) {
23457ec8bab3SRichard Henderson         case 32:
23467ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
23477ec8bab3SRichard Henderson             return;
23487ec8bab3SRichard Henderson         case 16:
23497ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23507ec8bab3SRichard Henderson             return;
23517ec8bab3SRichard Henderson         case 8:
23527ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23537ec8bab3SRichard Henderson             return;
23547ec8bab3SRichard Henderson         }
23557ec8bab3SRichard Henderson     }
23567ec8bab3SRichard Henderson 
23577ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
23587ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
23597ec8bab3SRichard Henderson         if (ofs >= 32) {
23607ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
23617ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
23627ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
23637ec8bab3SRichard Henderson         } else if (ofs == 0) {
23647ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
23657ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
23667ec8bab3SRichard Henderson             return;
23677ec8bab3SRichard Henderson         } else if (len > 32) {
23687ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
23697ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
23707ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
23717ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
23727ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23737ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
23747ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
23757ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
23767ec8bab3SRichard Henderson             return;
23777ec8bab3SRichard Henderson         } else {
23787ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
23797ec8bab3SRichard Henderson                field sits at the MSB.  */
23807ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
23817ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
23827ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
23837ec8bab3SRichard Henderson         }
23847ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
23857ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
23867ec8bab3SRichard Henderson         return;
23877ec8bab3SRichard Henderson     }
23887ec8bab3SRichard Henderson 
23897ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
23907ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
23917ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
23927ec8bab3SRichard Henderson         return;
23937ec8bab3SRichard Henderson     }
23947ec8bab3SRichard Henderson 
23957ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
23967ec8bab3SRichard Henderson     switch (ofs + len) {
23977ec8bab3SRichard Henderson     case 32:
23987ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23997ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
24007ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
24017ec8bab3SRichard Henderson             return;
24027ec8bab3SRichard Henderson         }
24037ec8bab3SRichard Henderson         break;
24047ec8bab3SRichard Henderson     case 16:
24057ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
24067ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
24077ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
24087ec8bab3SRichard Henderson             return;
24097ec8bab3SRichard Henderson         }
24107ec8bab3SRichard Henderson         break;
24117ec8bab3SRichard Henderson     case 8:
24127ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
24137ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
24147ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
24157ec8bab3SRichard Henderson             return;
24167ec8bab3SRichard Henderson         }
24177ec8bab3SRichard Henderson         break;
24187ec8bab3SRichard Henderson     }
24197ec8bab3SRichard Henderson     switch (len) {
24207ec8bab3SRichard Henderson     case 32:
24217ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
24227ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24237ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
24247ec8bab3SRichard Henderson             return;
24257ec8bab3SRichard Henderson         }
24267ec8bab3SRichard Henderson         break;
24277ec8bab3SRichard Henderson     case 16:
24287ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
24297ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24307ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
24317ec8bab3SRichard Henderson             return;
24327ec8bab3SRichard Henderson         }
24337ec8bab3SRichard Henderson         break;
24347ec8bab3SRichard Henderson     case 8:
24357ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
24367ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
24377ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
24387ec8bab3SRichard Henderson             return;
24397ec8bab3SRichard Henderson         }
24407ec8bab3SRichard Henderson         break;
24417ec8bab3SRichard Henderson     }
24427ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
24437ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
24447ec8bab3SRichard Henderson }
24457ec8bab3SRichard Henderson 
24462089fcc9SDavid Hildenbrand /*
24472089fcc9SDavid Hildenbrand  * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
24482089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
24492089fcc9SDavid Hildenbrand  */
24502089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
24512089fcc9SDavid Hildenbrand                           unsigned int ofs)
24522089fcc9SDavid Hildenbrand {
24532089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 64);
24542089fcc9SDavid Hildenbrand     if (ofs == 0) {
24552089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, al);
24562089fcc9SDavid Hildenbrand     } else if (ofs == 64) {
24572089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, ah);
24582089fcc9SDavid Hildenbrand     } else if (al == ah) {
24592089fcc9SDavid Hildenbrand         tcg_gen_rotri_i64(ret, al, ofs);
2460fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i64) {
2461fce1296fSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
24622089fcc9SDavid Hildenbrand     } else {
24632089fcc9SDavid Hildenbrand         TCGv_i64 t0 = tcg_temp_new_i64();
24642089fcc9SDavid Hildenbrand         tcg_gen_shri_i64(t0, al, ofs);
24652089fcc9SDavid Hildenbrand         tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs);
24662089fcc9SDavid Hildenbrand         tcg_temp_free_i64(t0);
24672089fcc9SDavid Hildenbrand     }
24682089fcc9SDavid Hildenbrand }
24692089fcc9SDavid Hildenbrand 
2470951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2471951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2472951c6300SRichard Henderson {
247337ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
247437ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
247537ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
247637ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
247737ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2478951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2479951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2480951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2481951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2482951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2483951c6300SRichard Henderson 
2484951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2485951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2486951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2487951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2488951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2489951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2490951c6300SRichard Henderson         } else {
2491951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2492951c6300SRichard Henderson 
2493951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2494951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2495951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2496951c6300SRichard Henderson 
2497951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2498951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2499951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2500951c6300SRichard Henderson         }
2501951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2502951c6300SRichard Henderson         tcg_temp_free_i32(t1);
25033a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2504951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2505951c6300SRichard Henderson     } else {
2506951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2507951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2508951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2509951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2510951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2511951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2512951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2513951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2514951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2515951c6300SRichard Henderson     }
2516951c6300SRichard Henderson }
2517951c6300SRichard Henderson 
2518951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2519951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2520951c6300SRichard Henderson {
2521951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2522951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2523951c6300SRichard Henderson     } else {
2524951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2525951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2526951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2527951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2528951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2529951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2530951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2531951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2532951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2533951c6300SRichard Henderson     }
2534951c6300SRichard Henderson }
2535951c6300SRichard Henderson 
2536951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2537951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2538951c6300SRichard Henderson {
2539951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2540951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2541951c6300SRichard Henderson     } else {
2542951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2543951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2544951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2545951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2546951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2547951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2548951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2549951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2550951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2551951c6300SRichard Henderson     }
2552951c6300SRichard Henderson }
2553951c6300SRichard Henderson 
2554951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2555951c6300SRichard Henderson {
2556951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2557951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2558951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2559951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2560951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2561951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2562951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2563951c6300SRichard Henderson         tcg_temp_free_i64(t);
2564951c6300SRichard Henderson     } else {
2565951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2566951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2567951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2568951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2569951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2570951c6300SRichard Henderson     }
2571951c6300SRichard Henderson }
2572951c6300SRichard Henderson 
2573951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2574951c6300SRichard Henderson {
2575951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2576951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2577951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2578951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2579951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2580951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2581951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2582951c6300SRichard Henderson         tcg_temp_free_i64(t);
2583951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2584951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2585951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2586951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2587951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2588951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2589951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2590951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2591951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2592951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2593951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2594951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2595951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2596951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2597951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2598951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2599951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2600951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2601951c6300SRichard Henderson     } else {
2602951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2603951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2604951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2605951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2606951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2607951c6300SRichard Henderson     }
2608951c6300SRichard Henderson }
2609951c6300SRichard Henderson 
26105087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
26115087abfbSRichard Henderson {
26125087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
26135087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
26145087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
26155087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
26165087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
26175087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
26185087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
26195087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
26205087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
26215087abfbSRichard Henderson     tcg_temp_free_i64(t0);
26225087abfbSRichard Henderson     tcg_temp_free_i64(t1);
26235087abfbSRichard Henderson     tcg_temp_free_i64(t2);
26245087abfbSRichard Henderson }
26255087abfbSRichard Henderson 
2626b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2627b87fb8cdSRichard Henderson {
2628b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2629b87fb8cdSRichard Henderson }
2630b87fb8cdSRichard Henderson 
2631b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2632b87fb8cdSRichard Henderson {
2633b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2634b87fb8cdSRichard Henderson }
2635b87fb8cdSRichard Henderson 
2636b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2637b87fb8cdSRichard Henderson {
2638b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2639b87fb8cdSRichard Henderson }
2640b87fb8cdSRichard Henderson 
2641b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2642b87fb8cdSRichard Henderson {
2643b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2644b87fb8cdSRichard Henderson }
2645b87fb8cdSRichard Henderson 
2646ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
2647ff1f11f7SRichard Henderson {
2648ff1f11f7SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
2649ff1f11f7SRichard Henderson 
2650ff1f11f7SRichard Henderson     tcg_gen_sari_i64(t, a, 63);
2651ff1f11f7SRichard Henderson     tcg_gen_xor_i64(ret, a, t);
2652ff1f11f7SRichard Henderson     tcg_gen_sub_i64(ret, ret, t);
2653ff1f11f7SRichard Henderson     tcg_temp_free_i64(t);
2654ff1f11f7SRichard Henderson }
2655ff1f11f7SRichard Henderson 
2656951c6300SRichard Henderson /* Size changing operations.  */
2657951c6300SRichard Henderson 
2658609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2659951c6300SRichard Henderson {
26603a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2661951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2662609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2663b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2664ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2665951c6300SRichard Henderson     } else {
2666dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2667609ad705SRichard Henderson     }
2668609ad705SRichard Henderson }
2669609ad705SRichard Henderson 
2670609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2671609ad705SRichard Henderson {
2672609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2673609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2674609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2675b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2676ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2677951c6300SRichard Henderson     } else {
2678951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2679609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2680dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2681951c6300SRichard Henderson         tcg_temp_free_i64(t);
2682951c6300SRichard Henderson     }
2683951c6300SRichard Henderson }
2684951c6300SRichard Henderson 
2685951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2686951c6300SRichard Henderson {
26873a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2688951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2689951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
26903a13c3f3SRichard Henderson     } else {
2691b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2692ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26933a13c3f3SRichard Henderson     }
2694951c6300SRichard Henderson }
2695951c6300SRichard Henderson 
2696951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2697951c6300SRichard Henderson {
26983a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2699951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2700951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
27013a13c3f3SRichard Henderson     } else {
2702b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2703ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
27043a13c3f3SRichard Henderson     }
2705951c6300SRichard Henderson }
2706951c6300SRichard Henderson 
2707951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2708951c6300SRichard Henderson {
27093a13c3f3SRichard Henderson     TCGv_i64 tmp;
27103a13c3f3SRichard Henderson 
27113a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2712951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2713951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
27143a13c3f3SRichard Henderson         return;
27153a13c3f3SRichard Henderson     }
27163a13c3f3SRichard Henderson 
27173a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2718951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2719951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2720951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2721951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2722951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2723951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2724951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2725951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2726951c6300SRichard Henderson     } else {
2727951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2728951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2729951c6300SRichard Henderson     }
2730951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2731951c6300SRichard Henderson }
2732951c6300SRichard Henderson 
2733951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2734951c6300SRichard Henderson {
27353a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2736951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2737951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
27383a13c3f3SRichard Henderson     } else {
2739609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2740609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
27413a13c3f3SRichard Henderson     }
2742951c6300SRichard Henderson }
2743951c6300SRichard Henderson 
2744951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2745951c6300SRichard Henderson {
2746951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2747951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2748951c6300SRichard Henderson }
2749951c6300SRichard Henderson 
2750*4771e71cSRichard Henderson void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg)
2751*4771e71cSRichard Henderson {
2752*4771e71cSRichard Henderson     tcg_gen_mov_i64(lo, TCGV128_LOW(arg));
2753*4771e71cSRichard Henderson     tcg_gen_mov_i64(hi, TCGV128_HIGH(arg));
2754*4771e71cSRichard Henderson }
2755*4771e71cSRichard Henderson 
2756*4771e71cSRichard Henderson void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi)
2757*4771e71cSRichard Henderson {
2758*4771e71cSRichard Henderson     tcg_gen_mov_i64(TCGV128_LOW(ret), lo);
2759*4771e71cSRichard Henderson     tcg_gen_mov_i64(TCGV128_HIGH(ret), hi);
2760*4771e71cSRichard Henderson }
2761*4771e71cSRichard Henderson 
2762*4771e71cSRichard Henderson void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src)
2763*4771e71cSRichard Henderson {
2764*4771e71cSRichard Henderson     if (dst != src) {
2765*4771e71cSRichard Henderson         tcg_gen_mov_i64(TCGV128_LOW(dst), TCGV128_LOW(src));
2766*4771e71cSRichard Henderson         tcg_gen_mov_i64(TCGV128_HIGH(dst), TCGV128_HIGH(src));
2767*4771e71cSRichard Henderson     }
2768*4771e71cSRichard Henderson }
2769*4771e71cSRichard Henderson 
2770951c6300SRichard Henderson /* QEMU specific operations.  */
2771951c6300SRichard Henderson 
2772d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
277307ea28b4SRichard Henderson {
2774eba40358SRichard Henderson     /*
2775eba40358SRichard Henderson      * Let the jit code return the read-only version of the
2776eba40358SRichard Henderson      * TranslationBlock, so that we minimize the pc-relative
2777eba40358SRichard Henderson      * distance of the address of the exit_tb code to TB.
2778eba40358SRichard Henderson      * This will improve utilization of pc-relative address loads.
2779eba40358SRichard Henderson      *
2780eba40358SRichard Henderson      * TODO: Move this to translator_loop, so that all const
2781eba40358SRichard Henderson      * TranslationBlock pointers refer to read-only memory.
2782eba40358SRichard Henderson      * This requires coordination with targets that do not use
2783eba40358SRichard Henderson      * the translator_loop.
2784eba40358SRichard Henderson      */
2785eba40358SRichard Henderson     uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx;
278607ea28b4SRichard Henderson 
278707ea28b4SRichard Henderson     if (tb == NULL) {
278807ea28b4SRichard Henderson         tcg_debug_assert(idx == 0);
278907ea28b4SRichard Henderson     } else if (idx <= TB_EXIT_IDXMAX) {
279007ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG
279107ea28b4SRichard Henderson         /* This is an exit following a goto_tb.  Verify that we have
279207ea28b4SRichard Henderson            seen this numbered exit before, via tcg_gen_goto_tb.  */
279307ea28b4SRichard Henderson         tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
279407ea28b4SRichard Henderson #endif
279507ea28b4SRichard Henderson     } else {
279607ea28b4SRichard Henderson         /* This is an exit via the exitreq label.  */
279707ea28b4SRichard Henderson         tcg_debug_assert(idx == TB_EXIT_REQUESTED);
279807ea28b4SRichard Henderson     }
279907ea28b4SRichard Henderson 
2800e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
280107ea28b4SRichard Henderson     tcg_gen_op1i(INDEX_op_exit_tb, val);
280207ea28b4SRichard Henderson }
280307ea28b4SRichard Henderson 
2804951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2805951c6300SRichard Henderson {
280684f15616SRichard Henderson     /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
2807b7e4afbdSRichard Henderson     tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB));
2808951c6300SRichard Henderson     /* We only support two chained exits.  */
280907ea28b4SRichard Henderson     tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
2810951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2811a4761232SPhilippe Mathieu-Daudé     /* Verify that we haven't seen this numbered exit before.  */
2812b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2813b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2814951c6300SRichard Henderson #endif
2815e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2816951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2817951c6300SRichard Henderson }
2818951c6300SRichard Henderson 
28197f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2820cedbcb01SEmilio G. Cota {
2821e6d86bedSEmilio G. Cota     TCGv_ptr ptr;
2822e6d86bedSEmilio G. Cota 
2823b7e4afbdSRichard Henderson     if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) {
282484f15616SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
282584f15616SRichard Henderson         return;
282684f15616SRichard Henderson     }
282784f15616SRichard Henderson 
2828e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2829e6d86bedSEmilio G. Cota     ptr = tcg_temp_new_ptr();
28301c2adb95SRichard Henderson     gen_helper_lookup_tb_ptr(ptr, cpu_env);
2831ae8b75dcSRichard Henderson     tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2832cedbcb01SEmilio G. Cota     tcg_temp_free_ptr(ptr);
2833cedbcb01SEmilio G. Cota }
2834cedbcb01SEmilio G. Cota 
283514776ab5STony Nguyen static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
2836951c6300SRichard Henderson {
28371f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
283876e366e7SRichard Henderson     unsigned a_bits = get_alignment_bits(op);
283976e366e7SRichard Henderson 
284076e366e7SRichard Henderson     /* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */
284176e366e7SRichard Henderson     if (a_bits == (op & MO_SIZE)) {
284276e366e7SRichard Henderson         op = (op & ~MO_AMASK) | MO_ALIGN;
284376e366e7SRichard Henderson     }
28441f00b27fSSergey Sorokin 
2845951c6300SRichard Henderson     switch (op & MO_SIZE) {
2846951c6300SRichard Henderson     case MO_8:
2847951c6300SRichard Henderson         op &= ~MO_BSWAP;
2848951c6300SRichard Henderson         break;
2849951c6300SRichard Henderson     case MO_16:
2850951c6300SRichard Henderson         break;
2851951c6300SRichard Henderson     case MO_32:
2852951c6300SRichard Henderson         if (!is64) {
2853951c6300SRichard Henderson             op &= ~MO_SIGN;
2854951c6300SRichard Henderson         }
2855951c6300SRichard Henderson         break;
2856951c6300SRichard Henderson     case MO_64:
28574b473e0cSRichard Henderson         if (is64) {
28584b473e0cSRichard Henderson             op &= ~MO_SIGN;
2859951c6300SRichard Henderson             break;
2860951c6300SRichard Henderson         }
28614b473e0cSRichard Henderson         /* fall through */
28624b473e0cSRichard Henderson     default:
28634b473e0cSRichard Henderson         g_assert_not_reached();
28644b473e0cSRichard Henderson     }
2865951c6300SRichard Henderson     if (st) {
2866951c6300SRichard Henderson         op &= ~MO_SIGN;
2867951c6300SRichard Henderson     }
2868951c6300SRichard Henderson     return op;
2869951c6300SRichard Henderson }
2870951c6300SRichard Henderson 
2871c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
287214776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2873951c6300SRichard Henderson {
28749002ffcbSRichard Henderson     MemOpIdx oi = make_memop_idx(memop, idx);
2875951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
287659227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2877951c6300SRichard Henderson #else
2878c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
287959227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2880c45cb8bbSRichard Henderson     } else {
2881ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2882c45cb8bbSRichard Henderson     }
2883951c6300SRichard Henderson #endif
2884c45cb8bbSRichard Henderson }
2885c45cb8bbSRichard Henderson 
2886c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
288714776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2888c45cb8bbSRichard Henderson {
28899002ffcbSRichard Henderson     MemOpIdx oi = make_memop_idx(memop, idx);
2890c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2891c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
289259227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2893c45cb8bbSRichard Henderson     } else {
2894ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2895c45cb8bbSRichard Henderson     }
2896c45cb8bbSRichard Henderson #else
2897c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
289859227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
289959227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2900c45cb8bbSRichard Henderson     } else {
290159227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2902c45cb8bbSRichard Henderson     }
2903c45cb8bbSRichard Henderson #endif
2904c45cb8bbSRichard Henderson }
2905951c6300SRichard Henderson 
2906b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2907b32dc337SPranith Kumar {
2908b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2909b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2910b32dc337SPranith Kumar #endif
2911b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2912b32dc337SPranith Kumar     if (type) {
2913b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2914b32dc337SPranith Kumar     }
2915b32dc337SPranith Kumar }
2916b32dc337SPranith Kumar 
2917fcc54ab5SAlex Bennée static inline TCGv plugin_prep_mem_callbacks(TCGv vaddr)
2918fcc54ab5SAlex Bennée {
2919fcc54ab5SAlex Bennée #ifdef CONFIG_PLUGIN
2920fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
2921fcc54ab5SAlex Bennée         /* Save a copy of the vaddr for use after a load.  */
2922fcc54ab5SAlex Bennée         TCGv temp = tcg_temp_new();
2923fcc54ab5SAlex Bennée         tcg_gen_mov_tl(temp, vaddr);
2924fcc54ab5SAlex Bennée         return temp;
2925fcc54ab5SAlex Bennée     }
2926fcc54ab5SAlex Bennée #endif
2927fcc54ab5SAlex Bennée     return vaddr;
2928fcc54ab5SAlex Bennée }
2929fcc54ab5SAlex Bennée 
293037aff087SRichard Henderson static void plugin_gen_mem_callbacks(TCGv vaddr, MemOpIdx oi,
293137aff087SRichard Henderson                                      enum qemu_plugin_mem_rw rw)
2932e6d86bedSEmilio G. Cota {
2933e6d86bedSEmilio G. Cota #ifdef CONFIG_PLUGIN
2934fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
293537aff087SRichard Henderson         qemu_plugin_meminfo_t info = make_plugin_meminfo(oi, rw);
2936e6d86bedSEmilio G. Cota         plugin_gen_empty_mem_callback(vaddr, info);
2937fcc54ab5SAlex Bennée         tcg_temp_free(vaddr);
2938fcc54ab5SAlex Bennée     }
2939e6d86bedSEmilio G. Cota #endif
2940e6d86bedSEmilio G. Cota }
2941e6d86bedSEmilio G. Cota 
294214776ab5STony Nguyen void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2943951c6300SRichard Henderson {
294414776ab5STony Nguyen     MemOp orig_memop;
294537aff087SRichard Henderson     MemOpIdx oi;
2946e1dcf352SRichard Henderson 
2947b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2948951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
294937aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
2950e1dcf352SRichard Henderson 
2951e1dcf352SRichard Henderson     orig_memop = memop;
2952e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2953e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2954359feba5SRichard Henderson         /* The bswap primitive benefits from zero-extended input.  */
2955e1dcf352SRichard Henderson         if ((memop & MO_SSIZE) == MO_SW) {
2956e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2957e1dcf352SRichard Henderson         }
2958e1dcf352SRichard Henderson     }
2959e1dcf352SRichard Henderson 
2960fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2961c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
296237aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R);
2963e1dcf352SRichard Henderson 
2964e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2965e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2966e1dcf352SRichard Henderson         case MO_16:
2967359feba5SRichard Henderson             tcg_gen_bswap16_i32(val, val, (orig_memop & MO_SIGN
2968359feba5SRichard Henderson                                            ? TCG_BSWAP_IZ | TCG_BSWAP_OS
2969359feba5SRichard Henderson                                            : TCG_BSWAP_IZ | TCG_BSWAP_OZ));
2970e1dcf352SRichard Henderson             break;
2971e1dcf352SRichard Henderson         case MO_32:
2972e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(val, val);
2973e1dcf352SRichard Henderson             break;
2974e1dcf352SRichard Henderson         default:
2975e1dcf352SRichard Henderson             g_assert_not_reached();
2976e1dcf352SRichard Henderson         }
2977e1dcf352SRichard Henderson     }
2978951c6300SRichard Henderson }
2979951c6300SRichard Henderson 
298014776ab5STony Nguyen void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2981951c6300SRichard Henderson {
2982e1dcf352SRichard Henderson     TCGv_i32 swap = NULL;
298337aff087SRichard Henderson     MemOpIdx oi;
2984e1dcf352SRichard Henderson 
2985b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2986951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
298737aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
2988e1dcf352SRichard Henderson 
2989e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2990e1dcf352SRichard Henderson         swap = tcg_temp_new_i32();
2991e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
2992e1dcf352SRichard Henderson         case MO_16:
2993b53357acSRichard Henderson             tcg_gen_bswap16_i32(swap, val, 0);
2994e1dcf352SRichard Henderson             break;
2995e1dcf352SRichard Henderson         case MO_32:
2996e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(swap, val);
2997e1dcf352SRichard Henderson             break;
2998e1dcf352SRichard Henderson         default:
2999e1dcf352SRichard Henderson             g_assert_not_reached();
3000e1dcf352SRichard Henderson         }
3001e1dcf352SRichard Henderson         val = swap;
3002e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
3003e1dcf352SRichard Henderson     }
3004e1dcf352SRichard Henderson 
3005fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
300607ce0b05SRichard Henderson     if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) {
300707ce0b05SRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx);
300807ce0b05SRichard Henderson     } else {
3009c45cb8bbSRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
301007ce0b05SRichard Henderson     }
301137aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
3012e1dcf352SRichard Henderson 
3013e1dcf352SRichard Henderson     if (swap) {
3014e1dcf352SRichard Henderson         tcg_temp_free_i32(swap);
3015e1dcf352SRichard Henderson     }
3016951c6300SRichard Henderson }
3017951c6300SRichard Henderson 
301814776ab5STony Nguyen void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
3019951c6300SRichard Henderson {
302014776ab5STony Nguyen     MemOp orig_memop;
302137aff087SRichard Henderson     MemOpIdx oi;
3022e1dcf352SRichard Henderson 
30233a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
3024951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
3025951c6300SRichard Henderson         if (memop & MO_SIGN) {
3026951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
3027951c6300SRichard Henderson         } else {
3028951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
3029951c6300SRichard Henderson         }
3030951c6300SRichard Henderson         return;
3031951c6300SRichard Henderson     }
3032951c6300SRichard Henderson 
3033e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
3034c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
303537aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
3036e1dcf352SRichard Henderson 
3037e1dcf352SRichard Henderson     orig_memop = memop;
3038e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
3039e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
3040359feba5SRichard Henderson         /* The bswap primitive benefits from zero-extended input.  */
3041e1dcf352SRichard Henderson         if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
3042e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
3043e1dcf352SRichard Henderson         }
3044e1dcf352SRichard Henderson     }
3045e1dcf352SRichard Henderson 
3046fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
3047c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
304837aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R);
3049e1dcf352SRichard Henderson 
3050e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
3051359feba5SRichard Henderson         int flags = (orig_memop & MO_SIGN
3052359feba5SRichard Henderson                      ? TCG_BSWAP_IZ | TCG_BSWAP_OS
3053359feba5SRichard Henderson                      : TCG_BSWAP_IZ | TCG_BSWAP_OZ);
3054e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
3055e1dcf352SRichard Henderson         case MO_16:
3056359feba5SRichard Henderson             tcg_gen_bswap16_i64(val, val, flags);
3057e1dcf352SRichard Henderson             break;
3058e1dcf352SRichard Henderson         case MO_32:
3059359feba5SRichard Henderson             tcg_gen_bswap32_i64(val, val, flags);
3060e1dcf352SRichard Henderson             break;
3061e1dcf352SRichard Henderson         case MO_64:
3062e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(val, val);
3063e1dcf352SRichard Henderson             break;
3064e1dcf352SRichard Henderson         default:
3065e1dcf352SRichard Henderson             g_assert_not_reached();
3066e1dcf352SRichard Henderson         }
3067e1dcf352SRichard Henderson     }
3068951c6300SRichard Henderson }
3069951c6300SRichard Henderson 
307014776ab5STony Nguyen void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
3071951c6300SRichard Henderson {
3072e1dcf352SRichard Henderson     TCGv_i64 swap = NULL;
307337aff087SRichard Henderson     MemOpIdx oi;
3074e1dcf352SRichard Henderson 
30753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
3076951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
3077951c6300SRichard Henderson         return;
3078951c6300SRichard Henderson     }
3079951c6300SRichard Henderson 
3080e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
3081c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
308237aff087SRichard Henderson     oi = make_memop_idx(memop, idx);
3083e1dcf352SRichard Henderson 
3084e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
3085e1dcf352SRichard Henderson         swap = tcg_temp_new_i64();
3086e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
3087e1dcf352SRichard Henderson         case MO_16:
3088b53357acSRichard Henderson             tcg_gen_bswap16_i64(swap, val, 0);
3089e1dcf352SRichard Henderson             break;
3090e1dcf352SRichard Henderson         case MO_32:
3091b53357acSRichard Henderson             tcg_gen_bswap32_i64(swap, val, 0);
3092e1dcf352SRichard Henderson             break;
3093e1dcf352SRichard Henderson         case MO_64:
3094e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(swap, val);
3095e1dcf352SRichard Henderson             break;
3096e1dcf352SRichard Henderson         default:
3097e1dcf352SRichard Henderson             g_assert_not_reached();
3098e1dcf352SRichard Henderson         }
3099e1dcf352SRichard Henderson         val = swap;
3100e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
3101e1dcf352SRichard Henderson     }
3102e1dcf352SRichard Henderson 
3103fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
3104c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
310537aff087SRichard Henderson     plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
3106e1dcf352SRichard Henderson 
3107e1dcf352SRichard Henderson     if (swap) {
3108e1dcf352SRichard Henderson         tcg_temp_free_i64(swap);
3109e1dcf352SRichard Henderson     }
3110951c6300SRichard Henderson }
3111c482cb11SRichard Henderson 
311214776ab5STony Nguyen static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
3113c482cb11SRichard Henderson {
3114c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3115c482cb11SRichard Henderson     case MO_SB:
3116c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
3117c482cb11SRichard Henderson         break;
3118c482cb11SRichard Henderson     case MO_UB:
3119c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
3120c482cb11SRichard Henderson         break;
3121c482cb11SRichard Henderson     case MO_SW:
3122c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
3123c482cb11SRichard Henderson         break;
3124c482cb11SRichard Henderson     case MO_UW:
3125c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
3126c482cb11SRichard Henderson         break;
3127c482cb11SRichard Henderson     default:
3128c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
3129c482cb11SRichard Henderson         break;
3130c482cb11SRichard Henderson     }
3131c482cb11SRichard Henderson }
3132c482cb11SRichard Henderson 
313314776ab5STony Nguyen static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
3134c482cb11SRichard Henderson {
3135c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3136c482cb11SRichard Henderson     case MO_SB:
3137c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
3138c482cb11SRichard Henderson         break;
3139c482cb11SRichard Henderson     case MO_UB:
3140c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
3141c482cb11SRichard Henderson         break;
3142c482cb11SRichard Henderson     case MO_SW:
3143c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
3144c482cb11SRichard Henderson         break;
3145c482cb11SRichard Henderson     case MO_UW:
3146c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
3147c482cb11SRichard Henderson         break;
3148c482cb11SRichard Henderson     case MO_SL:
3149c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
3150c482cb11SRichard Henderson         break;
3151c482cb11SRichard Henderson     case MO_UL:
3152c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
3153c482cb11SRichard Henderson         break;
3154c482cb11SRichard Henderson     default:
3155c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
3156c482cb11SRichard Henderson         break;
3157c482cb11SRichard Henderson     }
3158c482cb11SRichard Henderson }
3159c482cb11SRichard Henderson 
3160c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
3161c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
3162c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
3163c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
3164c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
3165c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
3166c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
3167c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
3168c482cb11SRichard Henderson 
3169df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3170df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
3171df79b996SRichard Henderson #else
3172df79b996SRichard Henderson # define WITH_ATOMIC64(X)
3173df79b996SRichard Henderson #endif
3174df79b996SRichard Henderson 
31754b473e0cSRichard Henderson static void * const table_cmpxchg[(MO_SIZE | MO_BSWAP) + 1] = {
3176c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
3177c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
3178c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
3179c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
3180c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
3181df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
3182df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
3183c482cb11SRichard Henderson };
3184c482cb11SRichard Henderson 
3185c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
318614776ab5STony Nguyen                                 TCGv_i32 newv, TCGArg idx, MemOp memop)
3187c482cb11SRichard Henderson {
3188c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3189c482cb11SRichard Henderson 
3190b7e4afbdSRichard Henderson     if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
3191c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
3192c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
3193c482cb11SRichard Henderson 
3194c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
3195c482cb11SRichard Henderson 
3196c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
3197c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
3198c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3199c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
3200c482cb11SRichard Henderson 
3201c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3202c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
3203c482cb11SRichard Henderson         } else {
3204c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
3205c482cb11SRichard Henderson         }
3206c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
3207c482cb11SRichard Henderson     } else {
3208c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
32099002ffcbSRichard Henderson         MemOpIdx oi;
3210c482cb11SRichard Henderson 
3211c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3212c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3213c482cb11SRichard Henderson 
3214e28a8664SRichard Henderson         oi = make_memop_idx(memop & ~MO_SIGN, idx);
321511d11d61SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3216c482cb11SRichard Henderson 
3217c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3218c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
3219c482cb11SRichard Henderson         }
3220c482cb11SRichard Henderson     }
3221c482cb11SRichard Henderson }
3222c482cb11SRichard Henderson 
3223c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
322414776ab5STony Nguyen                                 TCGv_i64 newv, TCGArg idx, MemOp memop)
3225c482cb11SRichard Henderson {
3226c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3227c482cb11SRichard Henderson 
3228b7e4afbdSRichard Henderson     if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
3229c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
3230c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
3231c482cb11SRichard Henderson 
3232c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
3233c482cb11SRichard Henderson 
3234c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
3235c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
3236c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3237c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
3238c482cb11SRichard Henderson 
3239c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3240c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
3241c482cb11SRichard Henderson         } else {
3242c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
3243c482cb11SRichard Henderson         }
3244c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
3245c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
3246df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3247c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
32489002ffcbSRichard Henderson         MemOpIdx oi;
3249c482cb11SRichard Henderson 
3250c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3251c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3252c482cb11SRichard Henderson 
3253e28a8664SRichard Henderson         oi = make_memop_idx(memop, idx);
325411d11d61SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3255df79b996SRichard Henderson #else
32561c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
325779b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
325879b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
325979b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
3260df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3261c482cb11SRichard Henderson     } else {
3262c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
3263c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
3264c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3265c482cb11SRichard Henderson 
3266c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
3267c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
3268c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
3269c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
3270c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
3271c482cb11SRichard Henderson 
3272c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
3273c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3274c482cb11SRichard Henderson 
3275c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3276c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
3277c482cb11SRichard Henderson         }
3278c482cb11SRichard Henderson     }
3279c482cb11SRichard Henderson }
3280c482cb11SRichard Henderson 
3281c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
328214776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3283c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
3284c482cb11SRichard Henderson {
3285c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
3286c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
3287c482cb11SRichard Henderson 
3288c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3289c482cb11SRichard Henderson 
3290852f933eSRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop);
3291852f933eSRichard Henderson     tcg_gen_ext_i32(t2, val, memop);
3292852f933eSRichard Henderson     gen(t2, t1, t2);
3293c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3294c482cb11SRichard Henderson 
3295c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
3296c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
3297c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
3298c482cb11SRichard Henderson }
3299c482cb11SRichard Henderson 
3300c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
330114776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3302c482cb11SRichard Henderson {
3303c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
33049002ffcbSRichard Henderson     MemOpIdx oi;
3305c482cb11SRichard Henderson 
3306c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3307c482cb11SRichard Henderson 
3308c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
3309c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
3310c482cb11SRichard Henderson 
3311e28a8664SRichard Henderson     oi = make_memop_idx(memop & ~MO_SIGN, idx);
331211d11d61SRichard Henderson     gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
3313c482cb11SRichard Henderson 
3314c482cb11SRichard Henderson     if (memop & MO_SIGN) {
3315c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
3316c482cb11SRichard Henderson     }
3317c482cb11SRichard Henderson }
3318c482cb11SRichard Henderson 
3319c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
332014776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3321c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
3322c482cb11SRichard Henderson {
3323c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3324c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3325c482cb11SRichard Henderson 
3326c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3327c482cb11SRichard Henderson 
3328852f933eSRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop);
3329852f933eSRichard Henderson     tcg_gen_ext_i64(t2, val, memop);
3330852f933eSRichard Henderson     gen(t2, t1, t2);
3331c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3332c482cb11SRichard Henderson 
3333c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
3334c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
3335c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
3336c482cb11SRichard Henderson }
3337c482cb11SRichard Henderson 
3338c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
333914776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3340c482cb11SRichard Henderson {
3341c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3342c482cb11SRichard Henderson 
3343c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
3344df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3345c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
33469002ffcbSRichard Henderson         MemOpIdx oi;
3347c482cb11SRichard Henderson 
3348c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
3349c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3350c482cb11SRichard Henderson 
3351e28a8664SRichard Henderson         oi = make_memop_idx(memop & ~MO_SIGN, idx);
335211d11d61SRichard Henderson         gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
3353df79b996SRichard Henderson #else
33541c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
335579b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
335679b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
335779b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
3358df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3359c482cb11SRichard Henderson     } else {
3360c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
3361c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3362c482cb11SRichard Henderson 
3363c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
3364c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
3365c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
3366c482cb11SRichard Henderson 
3367c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
3368c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3369c482cb11SRichard Henderson 
3370c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3371c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
3372c482cb11SRichard Henderson         }
3373c482cb11SRichard Henderson     }
3374c482cb11SRichard Henderson }
3375c482cb11SRichard Henderson 
3376c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
33774b473e0cSRichard Henderson static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = {          \
3378c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
3379c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
3380c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
3381c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
3382c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
3383df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
3384df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3385c482cb11SRichard Henderson };                                                                      \
3386c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
338714776ab5STony Nguyen     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop)    \
3388c482cb11SRichard Henderson {                                                                       \
3389b7e4afbdSRichard Henderson     if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) {                        \
3390c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3391c482cb11SRichard Henderson     } else {                                                            \
3392c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3393c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3394c482cb11SRichard Henderson     }                                                                   \
3395c482cb11SRichard Henderson }                                                                       \
3396c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
339714776ab5STony Nguyen     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop)    \
3398c482cb11SRichard Henderson {                                                                       \
3399b7e4afbdSRichard Henderson     if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) {                        \
3400c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3401c482cb11SRichard Henderson     } else {                                                            \
3402c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3403c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3404c482cb11SRichard Henderson     }                                                                   \
3405c482cb11SRichard Henderson }
3406c482cb11SRichard Henderson 
3407c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3408c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3409c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3410c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
34115507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smin, smin, 0)
34125507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umin, umin, 0)
34135507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smax, smax, 0)
34145507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umax, umax, 0)
3415c482cb11SRichard Henderson 
3416c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3417c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3418c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3419c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
34205507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smin_fetch, smin, 1)
34215507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umin_fetch, umin, 1)
34225507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smax_fetch, smax, 1)
34235507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umax_fetch, umax, 1)
3424c482cb11SRichard Henderson 
3425c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3426c482cb11SRichard Henderson {
3427c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3428c482cb11SRichard Henderson }
3429c482cb11SRichard Henderson 
3430c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3431c482cb11SRichard Henderson {
3432c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3433c482cb11SRichard Henderson }
3434c482cb11SRichard Henderson 
3435c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3436c482cb11SRichard Henderson 
3437c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3438