xref: /openbmc/qemu/tcg/tcg-op.c (revision 4b473e0c)
1951c6300SRichard Henderson /*
2951c6300SRichard Henderson  * Tiny Code Generator for QEMU
3951c6300SRichard Henderson  *
4951c6300SRichard Henderson  * Copyright (c) 2008 Fabrice Bellard
5951c6300SRichard Henderson  *
6951c6300SRichard Henderson  * Permission is hereby granted, free of charge, to any person obtaining a copy
7951c6300SRichard Henderson  * of this software and associated documentation files (the "Software"), to deal
8951c6300SRichard Henderson  * in the Software without restriction, including without limitation the rights
9951c6300SRichard Henderson  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10951c6300SRichard Henderson  * copies of the Software, and to permit persons to whom the Software is
11951c6300SRichard Henderson  * furnished to do so, subject to the following conditions:
12951c6300SRichard Henderson  *
13951c6300SRichard Henderson  * The above copyright notice and this permission notice shall be included in
14951c6300SRichard Henderson  * all copies or substantial portions of the Software.
15951c6300SRichard Henderson  *
16951c6300SRichard Henderson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17951c6300SRichard Henderson  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18951c6300SRichard Henderson  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19951c6300SRichard Henderson  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20951c6300SRichard Henderson  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21951c6300SRichard Henderson  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22951c6300SRichard Henderson  * THE SOFTWARE.
23951c6300SRichard Henderson  */
24951c6300SRichard Henderson 
25757e725bSPeter Maydell #include "qemu/osdep.h"
2663c91552SPaolo Bonzini #include "exec/exec-all.h"
27dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h"
28dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
29dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-mo.h"
30dcdaadb6SLluís Vilanova #include "trace-tcg.h"
31dcdaadb6SLluís Vilanova #include "trace/mem.h"
32e6d86bedSEmilio G. Cota #include "exec/plugin-gen.h"
33951c6300SRichard Henderson 
343a13c3f3SRichard Henderson /* Reduce the number of ifdefs below.  This assumes that all uses of
353a13c3f3SRichard Henderson    TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
363a13c3f3SRichard Henderson    the compiler can eliminate.  */
373a13c3f3SRichard Henderson #if TCG_TARGET_REG_BITS == 64
383a13c3f3SRichard Henderson extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
393a13c3f3SRichard Henderson extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
403a13c3f3SRichard Henderson #define TCGV_LOW  TCGV_LOW_link_error
413a13c3f3SRichard Henderson #define TCGV_HIGH TCGV_HIGH_link_error
423a13c3f3SRichard Henderson #endif
43951c6300SRichard Henderson 
44b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
45951c6300SRichard Henderson {
46b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
4775e8b9b7SRichard Henderson     op->args[0] = a1;
48951c6300SRichard Henderson }
49951c6300SRichard Henderson 
50b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
51951c6300SRichard Henderson {
52b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
5375e8b9b7SRichard Henderson     op->args[0] = a1;
5475e8b9b7SRichard Henderson     op->args[1] = a2;
55951c6300SRichard Henderson }
56951c6300SRichard Henderson 
57b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
58951c6300SRichard Henderson {
59b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
6075e8b9b7SRichard Henderson     op->args[0] = a1;
6175e8b9b7SRichard Henderson     op->args[1] = a2;
6275e8b9b7SRichard Henderson     op->args[2] = a3;
63951c6300SRichard Henderson }
64951c6300SRichard Henderson 
65b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
66951c6300SRichard Henderson {
67b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
6875e8b9b7SRichard Henderson     op->args[0] = a1;
6975e8b9b7SRichard Henderson     op->args[1] = a2;
7075e8b9b7SRichard Henderson     op->args[2] = a3;
7175e8b9b7SRichard Henderson     op->args[3] = a4;
72951c6300SRichard Henderson }
73951c6300SRichard Henderson 
74b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
75b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5)
76951c6300SRichard Henderson {
77b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
7875e8b9b7SRichard Henderson     op->args[0] = a1;
7975e8b9b7SRichard Henderson     op->args[1] = a2;
8075e8b9b7SRichard Henderson     op->args[2] = a3;
8175e8b9b7SRichard Henderson     op->args[3] = a4;
8275e8b9b7SRichard Henderson     op->args[4] = a5;
83951c6300SRichard Henderson }
84951c6300SRichard Henderson 
85b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
86b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5, TCGArg a6)
87951c6300SRichard Henderson {
88b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
8975e8b9b7SRichard Henderson     op->args[0] = a1;
9075e8b9b7SRichard Henderson     op->args[1] = a2;
9175e8b9b7SRichard Henderson     op->args[2] = a3;
9275e8b9b7SRichard Henderson     op->args[3] = a4;
9375e8b9b7SRichard Henderson     op->args[4] = a5;
9475e8b9b7SRichard Henderson     op->args[5] = a6;
95951c6300SRichard Henderson }
96951c6300SRichard Henderson 
97f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
98f65e19bcSPranith Kumar {
99b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {
100b7e8b17aSRichard Henderson         tcg_gen_op1(INDEX_op_mb, mb_type);
101f65e19bcSPranith Kumar     }
102f65e19bcSPranith Kumar }
103f65e19bcSPranith Kumar 
104951c6300SRichard Henderson /* 32 bit ops */
105951c6300SRichard Henderson 
10611d11d61SRichard Henderson void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
10711d11d61SRichard Henderson {
10811d11d61SRichard Henderson     tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
10911d11d61SRichard Henderson }
11011d11d61SRichard Henderson 
111951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
112951c6300SRichard Henderson {
113951c6300SRichard Henderson     /* some cases can be optimized here */
114951c6300SRichard Henderson     if (arg2 == 0) {
115951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
116951c6300SRichard Henderson     } else {
11711d11d61SRichard Henderson         tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
118951c6300SRichard Henderson     }
119951c6300SRichard Henderson }
120951c6300SRichard Henderson 
121951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
122951c6300SRichard Henderson {
123951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
124951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
125951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
126951c6300SRichard Henderson     } else {
12711d11d61SRichard Henderson         tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
128951c6300SRichard Henderson     }
129951c6300SRichard Henderson }
130951c6300SRichard Henderson 
131951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
132951c6300SRichard Henderson {
133951c6300SRichard Henderson     /* some cases can be optimized here */
134951c6300SRichard Henderson     if (arg2 == 0) {
135951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
136951c6300SRichard Henderson     } else {
13711d11d61SRichard Henderson         tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
138951c6300SRichard Henderson     }
139951c6300SRichard Henderson }
140951c6300SRichard Henderson 
141474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
142951c6300SRichard Henderson {
143951c6300SRichard Henderson     /* Some cases can be optimized here.  */
144951c6300SRichard Henderson     switch (arg2) {
145951c6300SRichard Henderson     case 0:
146951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
147951c6300SRichard Henderson         return;
148474b2e8fSRichard Henderson     case -1:
149951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
150951c6300SRichard Henderson         return;
151474b2e8fSRichard Henderson     case 0xff:
152951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
153951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
154951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
155951c6300SRichard Henderson             return;
156951c6300SRichard Henderson         }
157951c6300SRichard Henderson         break;
158474b2e8fSRichard Henderson     case 0xffff:
159951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
160951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
161951c6300SRichard Henderson             return;
162951c6300SRichard Henderson         }
163951c6300SRichard Henderson         break;
164951c6300SRichard Henderson     }
16511d11d61SRichard Henderson 
16611d11d61SRichard Henderson     tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
167951c6300SRichard Henderson }
168951c6300SRichard Henderson 
169951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
170951c6300SRichard Henderson {
171951c6300SRichard Henderson     /* Some cases can be optimized here.  */
172951c6300SRichard Henderson     if (arg2 == -1) {
173951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
174951c6300SRichard Henderson     } else if (arg2 == 0) {
175951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
176951c6300SRichard Henderson     } else {
17711d11d61SRichard Henderson         tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
178951c6300SRichard Henderson     }
179951c6300SRichard Henderson }
180951c6300SRichard Henderson 
181951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
182951c6300SRichard Henderson {
183951c6300SRichard Henderson     /* Some cases can be optimized here.  */
184951c6300SRichard Henderson     if (arg2 == 0) {
185951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
186951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
187951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
188951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
189951c6300SRichard Henderson     } else {
19011d11d61SRichard Henderson         tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
191951c6300SRichard Henderson     }
192951c6300SRichard Henderson }
193951c6300SRichard Henderson 
194474b2e8fSRichard Henderson void tcg_gen_shli_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_shl_i32(ret, arg1, tcg_constant_i32(arg2));
201951c6300SRichard Henderson     }
202951c6300SRichard Henderson }
203951c6300SRichard Henderson 
204474b2e8fSRichard Henderson void tcg_gen_shri_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_shr_i32(ret, arg1, tcg_constant_i32(arg2));
211951c6300SRichard Henderson     }
212951c6300SRichard Henderson }
213951c6300SRichard Henderson 
214474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
215951c6300SRichard Henderson {
216474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
217951c6300SRichard Henderson     if (arg2 == 0) {
218951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
219951c6300SRichard Henderson     } else {
22011d11d61SRichard Henderson         tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2));
221951c6300SRichard Henderson     }
222951c6300SRichard Henderson }
223951c6300SRichard Henderson 
22442a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
225951c6300SRichard Henderson {
226951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
22742a268c2SRichard Henderson         tcg_gen_br(l);
228951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
229d88a117eSRichard Henderson         l->refs++;
23042a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
231951c6300SRichard Henderson     }
232951c6300SRichard Henderson }
233951c6300SRichard Henderson 
23442a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
235951c6300SRichard Henderson {
23637ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
23737ed3bf1SRichard Henderson         tcg_gen_br(l);
23837ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
23911d11d61SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l);
240951c6300SRichard Henderson     }
24137ed3bf1SRichard Henderson }
242951c6300SRichard Henderson 
243951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
244951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
245951c6300SRichard Henderson {
246951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
247951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
248951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
249951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
250951c6300SRichard Henderson     } else {
251951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
252951c6300SRichard Henderson     }
253951c6300SRichard Henderson }
254951c6300SRichard Henderson 
255951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
256951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
257951c6300SRichard Henderson {
25811d11d61SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2));
259951c6300SRichard Henderson }
260951c6300SRichard Henderson 
261951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
262951c6300SRichard Henderson {
263b2e3ae94SRichard Henderson     if (arg2 == 0) {
264b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
265b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
266b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
267b2e3ae94SRichard Henderson     } else {
26811d11d61SRichard Henderson         tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2));
269951c6300SRichard Henderson     }
270b2e3ae94SRichard Henderson }
271951c6300SRichard Henderson 
272951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
273951c6300SRichard Henderson {
274951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
275951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
276951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
277951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
278951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
279951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
280951c6300SRichard Henderson         tcg_temp_free_i32(t0);
281951c6300SRichard Henderson     } else {
282951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
283951c6300SRichard Henderson     }
284951c6300SRichard Henderson }
285951c6300SRichard Henderson 
286951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
287951c6300SRichard Henderson {
288951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
289951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
290951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
291951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
292951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
293951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
294951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
295951c6300SRichard Henderson         tcg_temp_free_i32(t0);
296951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
297951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
298951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
299951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
300951c6300SRichard Henderson         tcg_temp_free_i32(t0);
301951c6300SRichard Henderson     } else {
302951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
303951c6300SRichard Henderson     }
304951c6300SRichard Henderson }
305951c6300SRichard Henderson 
306951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
307951c6300SRichard Henderson {
308951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
309951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
310951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
311951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
312951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
313951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
314951c6300SRichard Henderson         tcg_temp_free_i32(t0);
315951c6300SRichard Henderson     } else {
316951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
317951c6300SRichard Henderson     }
318951c6300SRichard Henderson }
319951c6300SRichard Henderson 
320951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
321951c6300SRichard Henderson {
322951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
323951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
324951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
325951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
326951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
327951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
328951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
329951c6300SRichard Henderson         tcg_temp_free_i32(t0);
330951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
331951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
332951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
333951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
334951c6300SRichard Henderson         tcg_temp_free_i32(t0);
335951c6300SRichard Henderson     } else {
336951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
337951c6300SRichard Henderson     }
338951c6300SRichard Henderson }
339951c6300SRichard Henderson 
340951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
341951c6300SRichard Henderson {
342951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
343951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
344951c6300SRichard Henderson     } else {
345951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
346951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
347951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
348951c6300SRichard Henderson         tcg_temp_free_i32(t0);
349951c6300SRichard Henderson     }
350951c6300SRichard Henderson }
351951c6300SRichard Henderson 
352951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
353951c6300SRichard Henderson {
354951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
355951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
356951c6300SRichard Henderson     } else {
357951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
358951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
359951c6300SRichard Henderson     }
360951c6300SRichard Henderson }
361951c6300SRichard Henderson 
362951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
363951c6300SRichard Henderson {
364951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
365951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
366951c6300SRichard Henderson     } else {
367951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
368951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
369951c6300SRichard Henderson     }
370951c6300SRichard Henderson }
371951c6300SRichard Henderson 
372951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
373951c6300SRichard Henderson {
374951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
375951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
376951c6300SRichard Henderson     } else {
377951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
378951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
379951c6300SRichard Henderson     }
380951c6300SRichard Henderson }
381951c6300SRichard Henderson 
382951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
383951c6300SRichard Henderson {
384951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
385951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
386951c6300SRichard Henderson     } else {
387951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
388951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
389951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
390951c6300SRichard Henderson         tcg_temp_free_i32(t0);
391951c6300SRichard Henderson     }
392951c6300SRichard Henderson }
393951c6300SRichard Henderson 
3940e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
3950e28d006SRichard Henderson {
3960e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
3970e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
3980e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
3990e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4000e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4010e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4020e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4030e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4040e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4050e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4060e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4070e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4080e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4090e28d006SRichard Henderson     } else {
4100e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4110e28d006SRichard Henderson     }
4120e28d006SRichard Henderson }
4130e28d006SRichard Henderson 
4140e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4150e28d006SRichard Henderson {
41611d11d61SRichard Henderson     tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2));
4170e28d006SRichard Henderson }
4180e28d006SRichard Henderson 
4190e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4200e28d006SRichard Henderson {
4210e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4220e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4230e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4240e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4250e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4260e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4270e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4280e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4290e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4300e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4310e28d006SRichard Henderson         tcg_temp_free_i64(t2);
43214e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
43314e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
43414e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
43514e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
43614e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
43714e99210SRichard Henderson 
43814e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
43914e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
44014e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
44114e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
44214e99210SRichard Henderson         } else {
44314e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
44414e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
44514e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
44614e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
44714e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
44814e99210SRichard Henderson         }
44911d11d61SRichard Henderson         z = tcg_constant_i32(0);
45014e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
45114e99210SRichard Henderson         tcg_temp_free_i32(t);
4520e28d006SRichard Henderson     } else {
4530e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4540e28d006SRichard Henderson     }
4550e28d006SRichard Henderson }
4560e28d006SRichard Henderson 
4570e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4580e28d006SRichard Henderson {
45914e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
46014e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
46114e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
46214e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
46314e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
46414e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
46514e99210SRichard Henderson         tcg_temp_free_i32(t);
46614e99210SRichard Henderson     } else {
46711d11d61SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2));
4680e28d006SRichard Henderson     }
46914e99210SRichard Henderson }
4700e28d006SRichard Henderson 
471086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
472086920c2SRichard Henderson {
473086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
474086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
475086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
476086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
477086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
478086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
479086920c2SRichard Henderson         tcg_temp_free_i32(t);
480086920c2SRichard Henderson     } else {
481086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
482086920c2SRichard Henderson     }
483086920c2SRichard Henderson }
484086920c2SRichard Henderson 
485a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
486a768e4e9SRichard Henderson {
487a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
488a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
489a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
490a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
491a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
492a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
493a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
494a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
495a768e4e9SRichard Henderson     } else {
496a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
497a768e4e9SRichard Henderson     }
498a768e4e9SRichard Henderson }
499a768e4e9SRichard Henderson 
500951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
501951c6300SRichard Henderson {
502951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
503951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
504951c6300SRichard Henderson     } else {
505951c6300SRichard Henderson         TCGv_i32 t0, t1;
506951c6300SRichard Henderson 
507951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
508951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
509951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
510951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
511951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
512951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
513951c6300SRichard Henderson         tcg_temp_free_i32(t0);
514951c6300SRichard Henderson         tcg_temp_free_i32(t1);
515951c6300SRichard Henderson     }
516951c6300SRichard Henderson }
517951c6300SRichard Henderson 
51807dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
519951c6300SRichard Henderson {
52007dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
521951c6300SRichard Henderson     /* some cases can be optimized here */
522951c6300SRichard Henderson     if (arg2 == 0) {
523951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
524951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
52511d11d61SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2));
526951c6300SRichard Henderson     } else {
527951c6300SRichard Henderson         TCGv_i32 t0, t1;
528951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
529951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
530951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
531951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
532951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
533951c6300SRichard Henderson         tcg_temp_free_i32(t0);
534951c6300SRichard Henderson         tcg_temp_free_i32(t1);
535951c6300SRichard Henderson     }
536951c6300SRichard Henderson }
537951c6300SRichard Henderson 
538951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
539951c6300SRichard Henderson {
540951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
541951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
542951c6300SRichard Henderson     } else {
543951c6300SRichard Henderson         TCGv_i32 t0, t1;
544951c6300SRichard Henderson 
545951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
546951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
547951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
548951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
549951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
550951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
551951c6300SRichard Henderson         tcg_temp_free_i32(t0);
552951c6300SRichard Henderson         tcg_temp_free_i32(t1);
553951c6300SRichard Henderson     }
554951c6300SRichard Henderson }
555951c6300SRichard Henderson 
55607dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
557951c6300SRichard Henderson {
55807dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
559951c6300SRichard Henderson     /* some cases can be optimized here */
560951c6300SRichard Henderson     if (arg2 == 0) {
561951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
562951c6300SRichard Henderson     } else {
563951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
564951c6300SRichard Henderson     }
565951c6300SRichard Henderson }
566951c6300SRichard Henderson 
567951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
568951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
569951c6300SRichard Henderson {
570951c6300SRichard Henderson     uint32_t mask;
571951c6300SRichard Henderson     TCGv_i32 t1;
572951c6300SRichard Henderson 
573951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
5740d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
575951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
576951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
577951c6300SRichard Henderson 
5780d0d309dSRichard Henderson     if (len == 32) {
579951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
580951c6300SRichard Henderson         return;
581951c6300SRichard Henderson     }
582951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
583951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
584951c6300SRichard Henderson         return;
585951c6300SRichard Henderson     }
586951c6300SRichard Henderson 
587951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
588951c6300SRichard Henderson 
589b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i32) {
590b0a60567SRichard Henderson         if (ofs + len == 32) {
591b0a60567SRichard Henderson             tcg_gen_shli_i32(t1, arg1, len);
592b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, t1, arg2, len);
593b0a60567SRichard Henderson             goto done;
594b0a60567SRichard Henderson         }
595b0a60567SRichard Henderson         if (ofs == 0) {
596b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, arg1, arg2, len);
597b0a60567SRichard Henderson             tcg_gen_rotli_i32(ret, ret, len);
598b0a60567SRichard Henderson             goto done;
599b0a60567SRichard Henderson         }
600b0a60567SRichard Henderson     }
601b0a60567SRichard Henderson 
602b0a60567SRichard Henderson     mask = (1u << len) - 1;
603951c6300SRichard Henderson     if (ofs + len < 32) {
604951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
605951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
606951c6300SRichard Henderson     } else {
607951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
608951c6300SRichard Henderson     }
609951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
610951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
611b0a60567SRichard Henderson  done:
612951c6300SRichard Henderson     tcg_temp_free_i32(t1);
613951c6300SRichard Henderson }
614951c6300SRichard Henderson 
61507cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
61607cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
61707cc68d5SRichard Henderson {
61807cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
61907cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
62007cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
62107cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
62207cc68d5SRichard Henderson 
62307cc68d5SRichard Henderson     if (ofs + len == 32) {
62407cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
62507cc68d5SRichard Henderson     } else if (ofs == 0) {
62607cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
62707cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
62807cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
62911d11d61SRichard Henderson         TCGv_i32 zero = tcg_constant_i32(0);
63007cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
63107cc68d5SRichard Henderson     } else {
63207cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
63307cc68d5SRichard Henderson            which allows ARG to stay live.  */
63407cc68d5SRichard Henderson         switch (len) {
63507cc68d5SRichard Henderson         case 16:
63607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
63707cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
63807cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
63907cc68d5SRichard Henderson                 return;
64007cc68d5SRichard Henderson             }
64107cc68d5SRichard Henderson             break;
64207cc68d5SRichard Henderson         case 8:
64307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
64407cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
64507cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
64607cc68d5SRichard Henderson                 return;
64707cc68d5SRichard Henderson             }
64807cc68d5SRichard Henderson             break;
64907cc68d5SRichard Henderson         }
65007cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
65107cc68d5SRichard Henderson         switch (ofs + len) {
65207cc68d5SRichard Henderson         case 16:
65307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
65407cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
65507cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
65607cc68d5SRichard Henderson                 return;
65707cc68d5SRichard Henderson             }
65807cc68d5SRichard Henderson             break;
65907cc68d5SRichard Henderson         case 8:
66007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
66107cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
66207cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
66307cc68d5SRichard Henderson                 return;
66407cc68d5SRichard Henderson             }
66507cc68d5SRichard Henderson             break;
66607cc68d5SRichard Henderson         }
66707cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
66807cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
66907cc68d5SRichard Henderson     }
67007cc68d5SRichard Henderson }
67107cc68d5SRichard Henderson 
6727ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
6737ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
6747ec8bab3SRichard Henderson {
6757ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
6767ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
6777ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
6787ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
6797ec8bab3SRichard Henderson 
6807ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
6817ec8bab3SRichard Henderson     if (ofs + len == 32) {
6827ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
6837ec8bab3SRichard Henderson         return;
6847ec8bab3SRichard Henderson     }
6857ec8bab3SRichard Henderson     if (ofs == 0) {
6867ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
6877ec8bab3SRichard Henderson         return;
6887ec8bab3SRichard Henderson     }
6897ec8bab3SRichard Henderson 
6907ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
6917ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
6927ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
6937ec8bab3SRichard Henderson         return;
6947ec8bab3SRichard Henderson     }
6957ec8bab3SRichard Henderson 
6967ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
6977ec8bab3SRichard Henderson     switch (ofs + len) {
6987ec8bab3SRichard Henderson     case 16:
6997ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7007ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7017ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7027ec8bab3SRichard Henderson             return;
7037ec8bab3SRichard Henderson         }
7047ec8bab3SRichard Henderson         break;
7057ec8bab3SRichard Henderson     case 8:
7067ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7077ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7087ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7097ec8bab3SRichard Henderson             return;
7107ec8bab3SRichard Henderson         }
7117ec8bab3SRichard Henderson         break;
7127ec8bab3SRichard Henderson     }
7137ec8bab3SRichard Henderson 
7147ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7157ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7167ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7177ec8bab3SRichard Henderson     switch (len) {
7187ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7197ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7207ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7217ec8bab3SRichard Henderson         break;
7227ec8bab3SRichard Henderson     default:
7237ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7247ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7257ec8bab3SRichard Henderson         break;
7267ec8bab3SRichard Henderson     }
7277ec8bab3SRichard Henderson }
7287ec8bab3SRichard Henderson 
7297ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7307ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7317ec8bab3SRichard Henderson {
7327ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7337ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7347ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7357ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7367ec8bab3SRichard Henderson 
7377ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7387ec8bab3SRichard Henderson     if (ofs + len == 32) {
7397ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7407ec8bab3SRichard Henderson         return;
7417ec8bab3SRichard Henderson     }
7427ec8bab3SRichard Henderson     if (ofs == 0) {
7437ec8bab3SRichard Henderson         switch (len) {
7447ec8bab3SRichard Henderson         case 16:
7457ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7467ec8bab3SRichard Henderson             return;
7477ec8bab3SRichard Henderson         case 8:
7487ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7497ec8bab3SRichard Henderson             return;
7507ec8bab3SRichard Henderson         }
7517ec8bab3SRichard Henderson     }
7527ec8bab3SRichard Henderson 
7537ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7547ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7557ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7567ec8bab3SRichard Henderson         return;
7577ec8bab3SRichard Henderson     }
7587ec8bab3SRichard Henderson 
7597ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7607ec8bab3SRichard Henderson     switch (ofs + len) {
7617ec8bab3SRichard Henderson     case 16:
7627ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7637ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7647ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7657ec8bab3SRichard Henderson             return;
7667ec8bab3SRichard Henderson         }
7677ec8bab3SRichard Henderson         break;
7687ec8bab3SRichard Henderson     case 8:
7697ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7707ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7717ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7727ec8bab3SRichard Henderson             return;
7737ec8bab3SRichard Henderson         }
7747ec8bab3SRichard Henderson         break;
7757ec8bab3SRichard Henderson     }
7767ec8bab3SRichard Henderson     switch (len) {
7777ec8bab3SRichard Henderson     case 16:
7787ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7797ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7807ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
7817ec8bab3SRichard Henderson             return;
7827ec8bab3SRichard Henderson         }
7837ec8bab3SRichard Henderson         break;
7847ec8bab3SRichard Henderson     case 8:
7857ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7867ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7877ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
7887ec8bab3SRichard Henderson             return;
7897ec8bab3SRichard Henderson         }
7907ec8bab3SRichard Henderson         break;
7917ec8bab3SRichard Henderson     }
7927ec8bab3SRichard Henderson 
7937ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7947ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
7957ec8bab3SRichard Henderson }
7967ec8bab3SRichard Henderson 
7972089fcc9SDavid Hildenbrand /*
7982089fcc9SDavid Hildenbrand  * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
7992089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
8002089fcc9SDavid Hildenbrand  */
8012089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
8022089fcc9SDavid Hildenbrand                           unsigned int ofs)
8032089fcc9SDavid Hildenbrand {
8042089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 32);
8052089fcc9SDavid Hildenbrand     if (ofs == 0) {
8062089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, al);
8072089fcc9SDavid Hildenbrand     } else if (ofs == 32) {
8082089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, ah);
8092089fcc9SDavid Hildenbrand     } else if (al == ah) {
8102089fcc9SDavid Hildenbrand         tcg_gen_rotri_i32(ret, al, ofs);
811fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i32) {
812fce1296fSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
8132089fcc9SDavid Hildenbrand     } else {
8142089fcc9SDavid Hildenbrand         TCGv_i32 t0 = tcg_temp_new_i32();
8152089fcc9SDavid Hildenbrand         tcg_gen_shri_i32(t0, al, ofs);
8162089fcc9SDavid Hildenbrand         tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs);
8172089fcc9SDavid Hildenbrand         tcg_temp_free_i32(t0);
8182089fcc9SDavid Hildenbrand     }
8192089fcc9SDavid Hildenbrand }
8202089fcc9SDavid Hildenbrand 
821951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
822951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
823951c6300SRichard Henderson {
82437ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
82537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
82637ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
82737ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
82837ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
829951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
830951c6300SRichard Henderson     } else {
831951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
832951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
833951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
834951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
835951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
836951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
837951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
838951c6300SRichard Henderson         tcg_temp_free_i32(t0);
839951c6300SRichard Henderson         tcg_temp_free_i32(t1);
840951c6300SRichard Henderson     }
841951c6300SRichard Henderson }
842951c6300SRichard Henderson 
843951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
844951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
845951c6300SRichard Henderson {
846951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
847951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
848951c6300SRichard Henderson     } else {
849951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
850951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
851951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
852951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
853951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
854951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
855951c6300SRichard Henderson         tcg_temp_free_i64(t0);
856951c6300SRichard Henderson         tcg_temp_free_i64(t1);
857951c6300SRichard Henderson     }
858951c6300SRichard Henderson }
859951c6300SRichard Henderson 
860951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
861951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
862951c6300SRichard Henderson {
863951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
864951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
865951c6300SRichard Henderson     } else {
866951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
867951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
868951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
869951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
870951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
871951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
872951c6300SRichard Henderson         tcg_temp_free_i64(t0);
873951c6300SRichard Henderson         tcg_temp_free_i64(t1);
874951c6300SRichard Henderson     }
875951c6300SRichard Henderson }
876951c6300SRichard Henderson 
877951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
878951c6300SRichard Henderson {
879951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
880951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
881951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
882951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
883951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
884951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
885951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
886951c6300SRichard Henderson         tcg_temp_free_i32(t);
887951c6300SRichard Henderson     } else {
888951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
889951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
890951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
891951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
892951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
893951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
894951c6300SRichard Henderson         tcg_temp_free_i64(t0);
895951c6300SRichard Henderson         tcg_temp_free_i64(t1);
896951c6300SRichard Henderson     }
897951c6300SRichard Henderson }
898951c6300SRichard Henderson 
899951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
900951c6300SRichard Henderson {
901951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
902951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
903951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
904951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
905951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
906951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
907951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
908951c6300SRichard Henderson         tcg_temp_free_i32(t);
909951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
910951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
911951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
912951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
913951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
914951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
915951c6300SRichard Henderson         /* Adjust for negative inputs.  */
916951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
917951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
918951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
919951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
920951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
921951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
922951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
923951c6300SRichard Henderson         tcg_temp_free_i32(t0);
924951c6300SRichard Henderson         tcg_temp_free_i32(t1);
925951c6300SRichard Henderson         tcg_temp_free_i32(t2);
926951c6300SRichard Henderson         tcg_temp_free_i32(t3);
927951c6300SRichard Henderson     } else {
928951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
929951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
930951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
931951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
932951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
933951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
934951c6300SRichard Henderson         tcg_temp_free_i64(t0);
935951c6300SRichard Henderson         tcg_temp_free_i64(t1);
936951c6300SRichard Henderson     }
937951c6300SRichard Henderson }
938951c6300SRichard Henderson 
9395087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9405087abfbSRichard Henderson {
9415087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9425087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9435087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9445087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9455087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9465087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9475087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9485087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9495087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9505087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9515087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9525087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9535087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9545087abfbSRichard Henderson     } else {
9555087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9565087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9575087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9585087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9595087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9605087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9615087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9625087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9635087abfbSRichard Henderson     }
9645087abfbSRichard Henderson }
9655087abfbSRichard Henderson 
966951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
967951c6300SRichard Henderson {
968951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
969951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
970951c6300SRichard Henderson     } else {
971951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
972951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
973951c6300SRichard Henderson     }
974951c6300SRichard Henderson }
975951c6300SRichard Henderson 
976951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
977951c6300SRichard Henderson {
978951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
979951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
980951c6300SRichard Henderson     } else {
981951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
982951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
983951c6300SRichard Henderson     }
984951c6300SRichard Henderson }
985951c6300SRichard Henderson 
986951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
987951c6300SRichard Henderson {
988951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
989951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
990951c6300SRichard Henderson     } else {
991951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
992951c6300SRichard Henderson     }
993951c6300SRichard Henderson }
994951c6300SRichard Henderson 
995951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
996951c6300SRichard Henderson {
997951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
998951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
999951c6300SRichard Henderson     } else {
1000951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1001951c6300SRichard Henderson     }
1002951c6300SRichard Henderson }
1003951c6300SRichard Henderson 
10042b836c2aSRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
1005951c6300SRichard Henderson {
10062b836c2aSRichard Henderson     /* Only one extension flag may be present. */
10072b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
10082b836c2aSRichard Henderson 
1009951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
10102b836c2aSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags);
1011951c6300SRichard Henderson     } else {
1012951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
10132b836c2aSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
1014951c6300SRichard Henderson 
10152b836c2aSRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);
10162b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
10172b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t0, t0);
10182b836c2aSRichard Henderson         }
10192b836c2aSRichard Henderson 
10202b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
10212b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 24);
10222b836c2aSRichard Henderson             tcg_gen_sari_i32(t1, t1, 16);
10232b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
10242b836c2aSRichard Henderson             tcg_gen_ext8u_i32(t1, arg);
10252b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, t1, 8);
10262b836c2aSRichard Henderson         } else {
10272b836c2aSRichard Henderson             tcg_gen_shli_i32(t1, arg, 8);
10282b836c2aSRichard Henderson         }
10292b836c2aSRichard Henderson 
10302b836c2aSRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1031951c6300SRichard Henderson         tcg_temp_free_i32(t0);
10322b836c2aSRichard Henderson         tcg_temp_free_i32(t1);
1033951c6300SRichard Henderson     }
1034951c6300SRichard Henderson }
1035951c6300SRichard Henderson 
1036951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1037951c6300SRichard Henderson {
1038951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1039587195bdSRichard Henderson         tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
1040951c6300SRichard Henderson     } else {
1041a686dc71SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1042a686dc71SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
104311d11d61SRichard Henderson         TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
1044951c6300SRichard Henderson 
1045a686dc71SRichard Henderson                                         /* arg = abcd */
1046a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);   /*  t0 = .abc */
1047a686dc71SRichard Henderson         tcg_gen_and_i32(t1, arg, t2);   /*  t1 = .b.d */
1048a686dc71SRichard Henderson         tcg_gen_and_i32(t0, t0, t2);    /*  t0 = .a.c */
1049a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = b.d. */
1050a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = badc */
1051951c6300SRichard Henderson 
1052a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, ret, 16);  /*  t0 = ..ba */
1053a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, ret, 16);  /*  t1 = dc.. */
1054a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = dcba */
1055951c6300SRichard Henderson 
1056951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1057951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1058951c6300SRichard Henderson     }
1059951c6300SRichard Henderson }
1060951c6300SRichard Henderson 
1061b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1062b87fb8cdSRichard Henderson {
1063b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1064b87fb8cdSRichard Henderson }
1065b87fb8cdSRichard Henderson 
1066b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1067b87fb8cdSRichard Henderson {
1068b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1069b87fb8cdSRichard Henderson }
1070b87fb8cdSRichard Henderson 
1071b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1072b87fb8cdSRichard Henderson {
1073b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1074b87fb8cdSRichard Henderson }
1075b87fb8cdSRichard Henderson 
1076b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1077b87fb8cdSRichard Henderson {
1078b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1079b87fb8cdSRichard Henderson }
1080b87fb8cdSRichard Henderson 
1081ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
1082ff1f11f7SRichard Henderson {
1083ff1f11f7SRichard Henderson     TCGv_i32 t = tcg_temp_new_i32();
1084ff1f11f7SRichard Henderson 
1085ff1f11f7SRichard Henderson     tcg_gen_sari_i32(t, a, 31);
1086ff1f11f7SRichard Henderson     tcg_gen_xor_i32(ret, a, t);
1087ff1f11f7SRichard Henderson     tcg_gen_sub_i32(ret, ret, t);
1088ff1f11f7SRichard Henderson     tcg_temp_free_i32(t);
1089ff1f11f7SRichard Henderson }
1090ff1f11f7SRichard Henderson 
1091951c6300SRichard Henderson /* 64-bit ops */
1092951c6300SRichard Henderson 
1093951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1094951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1095951c6300SRichard Henderson 
1096951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1097951c6300SRichard Henderson {
1098951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1099951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1100951c6300SRichard Henderson }
1101951c6300SRichard Henderson 
1102951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1103951c6300SRichard Henderson {
110411d11d61SRichard Henderson     TCGTemp *ts = tcgv_i64_temp(arg);
110511d11d61SRichard Henderson 
110611d11d61SRichard Henderson     /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
110711d11d61SRichard Henderson     if (ts->kind == TEMP_CONST) {
110811d11d61SRichard Henderson         tcg_gen_movi_i64(ret, ts->val);
110911d11d61SRichard Henderson     } else {
1110951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1111951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1112951c6300SRichard Henderson     }
111311d11d61SRichard Henderson }
1114951c6300SRichard Henderson 
1115951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1116951c6300SRichard Henderson {
1117951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1118951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1119951c6300SRichard Henderson }
1120951c6300SRichard Henderson 
1121951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1122951c6300SRichard Henderson {
1123951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1124951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1125951c6300SRichard Henderson }
1126951c6300SRichard Henderson 
1127951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1128951c6300SRichard Henderson {
1129951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11303ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1131951c6300SRichard Henderson }
1132951c6300SRichard Henderson 
1133951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1134951c6300SRichard Henderson {
1135951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1136951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1137951c6300SRichard Henderson }
1138951c6300SRichard Henderson 
1139951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1140951c6300SRichard Henderson {
1141951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1142951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1143951c6300SRichard Henderson }
1144951c6300SRichard Henderson 
1145951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1146951c6300SRichard Henderson {
1147951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1148951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1149951c6300SRichard Henderson }
1150951c6300SRichard Henderson 
1151951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1152951c6300SRichard Henderson {
1153951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1154951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1155951c6300SRichard Henderson }
1156951c6300SRichard Henderson 
1157951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1158951c6300SRichard Henderson {
1159951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1160951c6300SRichard Henderson        they cannot be the same temporary */
1161cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1162951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1163951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1164951c6300SRichard Henderson #else
1165951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1166951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1167951c6300SRichard Henderson #endif
1168951c6300SRichard Henderson }
1169951c6300SRichard Henderson 
1170951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1171951c6300SRichard Henderson {
1172cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1173951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1174951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1175951c6300SRichard Henderson #else
1176951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1177951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1178951c6300SRichard Henderson #endif
1179951c6300SRichard Henderson }
1180951c6300SRichard Henderson 
1181951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1182951c6300SRichard Henderson {
1183951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1184951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1185951c6300SRichard Henderson }
1186951c6300SRichard Henderson 
1187951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1188951c6300SRichard Henderson {
1189951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1190951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1191951c6300SRichard Henderson }
1192951c6300SRichard Henderson 
1193951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1194951c6300SRichard Henderson {
1195951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1196951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1197951c6300SRichard Henderson }
1198951c6300SRichard Henderson 
1199951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1200951c6300SRichard Henderson {
1201951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1202951c6300SRichard Henderson }
1203951c6300SRichard Henderson 
1204951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1205951c6300SRichard Henderson {
1206951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1207951c6300SRichard Henderson }
1208951c6300SRichard Henderson 
1209951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1210951c6300SRichard Henderson {
1211951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1212951c6300SRichard Henderson }
1213951c6300SRichard Henderson 
1214951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1215951c6300SRichard Henderson {
1216951c6300SRichard Henderson     TCGv_i64 t0;
1217951c6300SRichard Henderson     TCGv_i32 t1;
1218951c6300SRichard Henderson 
1219951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1220951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1221951c6300SRichard Henderson 
1222951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1223951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1224951c6300SRichard Henderson 
1225951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1226951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1227951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1228951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1229951c6300SRichard Henderson 
1230951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1231951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1232951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1233951c6300SRichard Henderson }
123411d11d61SRichard Henderson 
123511d11d61SRichard Henderson #else
123611d11d61SRichard Henderson 
123711d11d61SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
123811d11d61SRichard Henderson {
123911d11d61SRichard Henderson     tcg_gen_mov_i64(ret, tcg_constant_i64(arg));
124011d11d61SRichard Henderson }
124111d11d61SRichard Henderson 
1242951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1243951c6300SRichard Henderson 
1244951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1245951c6300SRichard Henderson {
1246951c6300SRichard Henderson     /* some cases can be optimized here */
1247951c6300SRichard Henderson     if (arg2 == 0) {
1248951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
124911d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
125011d11d61SRichard Henderson         tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2));
1251951c6300SRichard Henderson     } else {
125211d11d61SRichard Henderson         tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
125311d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
125411d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1255951c6300SRichard Henderson     }
1256951c6300SRichard Henderson }
1257951c6300SRichard Henderson 
1258951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1259951c6300SRichard Henderson {
1260951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1261951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1262951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
126311d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
126411d11d61SRichard Henderson         tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
1265951c6300SRichard Henderson     } else {
126611d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
126711d11d61SRichard Henderson                          tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32),
126811d11d61SRichard Henderson                          TCGV_LOW(arg2), TCGV_HIGH(arg2));
1269951c6300SRichard Henderson     }
1270951c6300SRichard Henderson }
1271951c6300SRichard Henderson 
1272951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1273951c6300SRichard Henderson {
1274951c6300SRichard Henderson     /* some cases can be optimized here */
1275951c6300SRichard Henderson     if (arg2 == 0) {
1276951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
127711d11d61SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 64) {
127811d11d61SRichard Henderson         tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2));
1279951c6300SRichard Henderson     } else {
128011d11d61SRichard Henderson         tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
128111d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
128211d11d61SRichard Henderson                          tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
1283951c6300SRichard Henderson     }
1284951c6300SRichard Henderson }
1285951c6300SRichard Henderson 
1286474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1287951c6300SRichard Henderson {
12883a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1289951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1290951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12913a13c3f3SRichard Henderson         return;
12923a13c3f3SRichard Henderson     }
12933a13c3f3SRichard Henderson 
1294951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1295951c6300SRichard Henderson     switch (arg2) {
1296951c6300SRichard Henderson     case 0:
1297951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1298951c6300SRichard Henderson         return;
1299474b2e8fSRichard Henderson     case -1:
1300951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1301951c6300SRichard Henderson         return;
1302474b2e8fSRichard Henderson     case 0xff:
1303951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1304951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1305951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1306951c6300SRichard Henderson             return;
1307951c6300SRichard Henderson         }
1308951c6300SRichard Henderson         break;
1309474b2e8fSRichard Henderson     case 0xffff:
1310951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1311951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1312951c6300SRichard Henderson             return;
1313951c6300SRichard Henderson         }
1314951c6300SRichard Henderson         break;
1315474b2e8fSRichard Henderson     case 0xffffffffu:
1316951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1317951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1318951c6300SRichard Henderson             return;
1319951c6300SRichard Henderson         }
1320951c6300SRichard Henderson         break;
1321951c6300SRichard Henderson     }
132211d11d61SRichard Henderson 
132311d11d61SRichard Henderson     tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2));
1324951c6300SRichard Henderson }
1325951c6300SRichard Henderson 
1326951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1327951c6300SRichard Henderson {
13283a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1329951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1330951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13313a13c3f3SRichard Henderson         return;
13323a13c3f3SRichard Henderson     }
1333951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1334951c6300SRichard Henderson     if (arg2 == -1) {
1335951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1336951c6300SRichard Henderson     } else if (arg2 == 0) {
1337951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1338951c6300SRichard Henderson     } else {
133911d11d61SRichard Henderson         tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2));
1340951c6300SRichard Henderson     }
1341951c6300SRichard Henderson }
1342951c6300SRichard Henderson 
1343951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1344951c6300SRichard Henderson {
13453a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1346951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1347951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13483a13c3f3SRichard Henderson         return;
13493a13c3f3SRichard Henderson     }
1350951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1351951c6300SRichard Henderson     if (arg2 == 0) {
1352951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1353951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1354951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1355951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1356951c6300SRichard Henderson     } else {
135711d11d61SRichard Henderson         tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2));
1358951c6300SRichard Henderson     }
1359951c6300SRichard Henderson }
1360951c6300SRichard Henderson 
1361951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1362951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1363951c6300SRichard Henderson {
1364951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1365951c6300SRichard Henderson     if (c == 0) {
1366951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1367951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1368951c6300SRichard Henderson     } else if (c >= 32) {
1369951c6300SRichard Henderson         c -= 32;
1370951c6300SRichard Henderson         if (right) {
1371951c6300SRichard Henderson             if (arith) {
1372951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1373951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1374951c6300SRichard Henderson             } else {
1375951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1376951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1377951c6300SRichard Henderson             }
1378951c6300SRichard Henderson         } else {
1379951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1380951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1381951c6300SRichard Henderson         }
138202616badSRichard Henderson     } else if (right) {
138302616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
138402616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_LOW(ret),
138502616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1386951c6300SRichard Henderson         } else {
1387951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
138802616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret),
138902616badSRichard Henderson                                 TCGV_HIGH(arg1), 32 - c, c);
1390951c6300SRichard Henderson         }
139102616badSRichard Henderson         if (arith) {
139202616badSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
139302616badSRichard Henderson         } else {
139402616badSRichard Henderson             tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
139502616badSRichard Henderson         }
139602616badSRichard Henderson     } else {
139702616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
139802616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_HIGH(ret),
139902616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
140002616badSRichard Henderson         } else {
140102616badSRichard Henderson             TCGv_i32 t0 = tcg_temp_new_i32();
140202616badSRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
140302616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), t0,
140402616badSRichard Henderson                                 TCGV_HIGH(arg1), c, 32 - c);
1405951c6300SRichard Henderson             tcg_temp_free_i32(t0);
140602616badSRichard Henderson         }
140702616badSRichard Henderson         tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1408951c6300SRichard Henderson     }
1409951c6300SRichard Henderson }
1410951c6300SRichard Henderson 
1411474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1412951c6300SRichard Henderson {
1413474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14153a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
14163a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1417951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1418951c6300SRichard Henderson     } else {
141911d11d61SRichard Henderson         tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2));
1420951c6300SRichard Henderson     }
1421951c6300SRichard Henderson }
1422951c6300SRichard Henderson 
1423474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1424951c6300SRichard Henderson {
1425474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14273a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
14283a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1429951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1430951c6300SRichard Henderson     } else {
143111d11d61SRichard Henderson         tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2));
1432951c6300SRichard Henderson     }
1433951c6300SRichard Henderson }
1434951c6300SRichard Henderson 
1435474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1436951c6300SRichard Henderson {
1437474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14393a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
14403a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1441951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1442951c6300SRichard Henderson     } else {
144311d11d61SRichard Henderson         tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2));
1444951c6300SRichard Henderson     }
1445951c6300SRichard Henderson }
1446951c6300SRichard Henderson 
144742a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1448951c6300SRichard Henderson {
1449951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
145042a268c2SRichard Henderson         tcg_gen_br(l);
1451951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1452d88a117eSRichard Henderson         l->refs++;
14533a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1454951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1455951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
145642a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14573a13c3f3SRichard Henderson         } else {
145842a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
145942a268c2SRichard Henderson                               label_arg(l));
14603a13c3f3SRichard Henderson         }
1461951c6300SRichard Henderson     }
1462951c6300SRichard Henderson }
1463951c6300SRichard Henderson 
146442a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1465951c6300SRichard Henderson {
146611d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
146711d11d61SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l);
146811d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
146942a268c2SRichard Henderson         tcg_gen_br(l);
1470951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
147111d11d61SRichard Henderson         l->refs++;
147211d11d61SRichard Henderson         tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
147311d11d61SRichard Henderson                           TCGV_LOW(arg1), TCGV_HIGH(arg1),
147411d11d61SRichard Henderson                           tcg_constant_i32(arg2),
147511d11d61SRichard Henderson                           tcg_constant_i32(arg2 >> 32),
147611d11d61SRichard Henderson                           cond, label_arg(l));
1477951c6300SRichard Henderson     }
1478951c6300SRichard Henderson }
1479951c6300SRichard Henderson 
1480951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1481951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1482951c6300SRichard Henderson {
1483951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1484951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1485951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1486951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1487951c6300SRichard Henderson     } else {
14883a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1489951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1490951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1491951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1492951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
14933a13c3f3SRichard Henderson         } else {
1494951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
14953a13c3f3SRichard Henderson         }
1496951c6300SRichard Henderson     }
1497951c6300SRichard Henderson }
1498951c6300SRichard Henderson 
1499951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1500951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1501951c6300SRichard Henderson {
150211d11d61SRichard Henderson     if (TCG_TARGET_REG_BITS == 64) {
150311d11d61SRichard Henderson         tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2));
150411d11d61SRichard Henderson     } else if (cond == TCG_COND_ALWAYS) {
150511d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 1);
150611d11d61SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
150711d11d61SRichard Henderson         tcg_gen_movi_i64(ret, 0);
150811d11d61SRichard Henderson     } else {
150911d11d61SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
151011d11d61SRichard Henderson                          TCGV_LOW(arg1), TCGV_HIGH(arg1),
151111d11d61SRichard Henderson                          tcg_constant_i32(arg2),
151211d11d61SRichard Henderson                          tcg_constant_i32(arg2 >> 32), cond);
151311d11d61SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
151411d11d61SRichard Henderson     }
1515951c6300SRichard Henderson }
1516951c6300SRichard Henderson 
1517951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1518951c6300SRichard Henderson {
1519b2e3ae94SRichard Henderson     if (arg2 == 0) {
1520b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1521b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1522b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1523b2e3ae94SRichard Henderson     } else {
1524951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1525951c6300SRichard Henderson         tcg_gen_mul_i64(ret, arg1, t0);
1526951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1527951c6300SRichard Henderson     }
1528b2e3ae94SRichard Henderson }
1529951c6300SRichard Henderson 
1530951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1531951c6300SRichard Henderson {
1532951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1533951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1534951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1535951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1536951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1537951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1538951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1539951c6300SRichard Henderson     } else {
1540951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1541951c6300SRichard Henderson     }
1542951c6300SRichard Henderson }
1543951c6300SRichard Henderson 
1544951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1545951c6300SRichard Henderson {
1546951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1547951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1548951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1549951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1550951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1551951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1552951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1553951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1554951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1555951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1556951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1557951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1558951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1559951c6300SRichard Henderson     } else {
1560951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1561951c6300SRichard Henderson     }
1562951c6300SRichard Henderson }
1563951c6300SRichard Henderson 
1564951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1565951c6300SRichard Henderson {
1566951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1567951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1568951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1569951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1570951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1571951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1572951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1573951c6300SRichard Henderson     } else {
1574951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1575951c6300SRichard Henderson     }
1576951c6300SRichard Henderson }
1577951c6300SRichard Henderson 
1578951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1579951c6300SRichard Henderson {
1580951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1581951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1582951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1583951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1584951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1585951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1586951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1587951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1588951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1589951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1590951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1591951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1592951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1593951c6300SRichard Henderson     } else {
1594951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1595951c6300SRichard Henderson     }
1596951c6300SRichard Henderson }
1597951c6300SRichard Henderson 
1598951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1599951c6300SRichard Henderson {
16003a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1601951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1602951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16033a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1604951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1605951c6300SRichard Henderson     } else {
1606951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1607951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1608951c6300SRichard Henderson     }
1609951c6300SRichard Henderson }
1610951c6300SRichard Henderson 
1611951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1612951c6300SRichard Henderson {
16133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1614951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1615951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16163a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1617951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1618951c6300SRichard Henderson     } else {
1619951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1620951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1621951c6300SRichard Henderson     }
1622951c6300SRichard Henderson }
1623951c6300SRichard Henderson 
1624951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1625951c6300SRichard Henderson {
16263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1627951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1628951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16293a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1630951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1631951c6300SRichard Henderson     } else {
1632951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1633951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1634951c6300SRichard Henderson     }
1635951c6300SRichard Henderson }
1636951c6300SRichard Henderson 
1637951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1638951c6300SRichard Henderson {
16393a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1640951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1641951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16423a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1643951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1644951c6300SRichard Henderson     } else {
1645951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1646951c6300SRichard Henderson     }
1647951c6300SRichard Henderson }
1648951c6300SRichard Henderson 
1649951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1650951c6300SRichard Henderson {
16513a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1652951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1653951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1655951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1656951c6300SRichard Henderson     } else {
1657951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1658951c6300SRichard Henderson     }
1659951c6300SRichard Henderson }
1660951c6300SRichard Henderson 
1661951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1662951c6300SRichard Henderson {
16633a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1664951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1665951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16663a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1667951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1668951c6300SRichard Henderson     } else {
1669951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1670951c6300SRichard Henderson     }
1671951c6300SRichard Henderson }
1672951c6300SRichard Henderson 
16732b836c2aSRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1674951c6300SRichard Henderson {
16752b836c2aSRichard Henderson     /* Only one extension flag may be present. */
16762b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
16772b836c2aSRichard Henderson 
16783a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
16792b836c2aSRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags);
16802b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
16812b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16822b836c2aSRichard Henderson         } else {
1683951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16842b836c2aSRichard Henderson         }
16853a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
16862b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags);
1687951c6300SRichard Henderson     } else {
1688951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
16892b836c2aSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1690951c6300SRichard Henderson 
16912b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);
16922b836c2aSRichard Henderson         if (!(flags & TCG_BSWAP_IZ)) {
16932b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t0, t0);
16942b836c2aSRichard Henderson         }
16952b836c2aSRichard Henderson 
16962b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
16972b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 56);
16982b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 48);
16992b836c2aSRichard Henderson         } else if (flags & TCG_BSWAP_OZ) {
17002b836c2aSRichard Henderson             tcg_gen_ext8u_i64(t1, arg);
17012b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, t1, 8);
17022b836c2aSRichard Henderson         } else {
17032b836c2aSRichard Henderson             tcg_gen_shli_i64(t1, arg, 8);
17042b836c2aSRichard Henderson         }
17052b836c2aSRichard Henderson 
17062b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1707951c6300SRichard Henderson         tcg_temp_free_i64(t0);
17082b836c2aSRichard Henderson         tcg_temp_free_i64(t1);
1709951c6300SRichard Henderson     }
1710951c6300SRichard Henderson }
1711951c6300SRichard Henderson 
17122b836c2aSRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
1713951c6300SRichard Henderson {
17142b836c2aSRichard Henderson     /* Only one extension flag may be present. */
17152b836c2aSRichard Henderson     tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
17162b836c2aSRichard Henderson 
17173a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1718951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17192b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17202b836c2aSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
17212b836c2aSRichard Henderson         } else {
1722951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17232b836c2aSRichard Henderson         }
17243a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
17252b836c2aSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags);
1726951c6300SRichard Henderson     } else {
1727a686dc71SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1728a686dc71SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
172911d11d61SRichard Henderson         TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
1730951c6300SRichard Henderson 
17312b836c2aSRichard Henderson                                             /* arg = xxxxabcd */
17322b836c2aSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);       /*  t0 = .xxxxabc */
1733a686dc71SRichard Henderson         tcg_gen_and_i64(t1, arg, t2);       /*  t1 = .....b.d */
1734a686dc71SRichard Henderson         tcg_gen_and_i64(t0, t0, t2);        /*  t0 = .....a.c */
1735a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);        /*  t1 = ....b.d. */
1736a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ....badc */
1737951c6300SRichard Henderson 
1738a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, ret, 48);      /*  t1 = dc...... */
1739a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);      /*  t0 = ......ba */
17402b836c2aSRichard Henderson         if (flags & TCG_BSWAP_OS) {
17412b836c2aSRichard Henderson             tcg_gen_sari_i64(t1, t1, 32);   /*  t1 = ssssdc.. */
17422b836c2aSRichard Henderson         } else {
1743a686dc71SRichard Henderson             tcg_gen_shri_i64(t1, t1, 32);   /*  t1 = ....dc.. */
17442b836c2aSRichard Henderson         }
17452b836c2aSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);        /* ret = ssssdcba */
1746951c6300SRichard Henderson 
1747951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1748951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1749951c6300SRichard Henderson     }
1750951c6300SRichard Henderson }
1751951c6300SRichard Henderson 
1752951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1753951c6300SRichard Henderson {
17543a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1755951c6300SRichard Henderson         TCGv_i32 t0, t1;
1756951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1757951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1758951c6300SRichard Henderson 
1759951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1760951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1761951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1762951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1763951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1764951c6300SRichard Henderson         tcg_temp_free_i32(t1);
17653a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1766587195bdSRichard Henderson         tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
1767951c6300SRichard Henderson     } else {
1768951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1769951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
17709e821eabSRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
1771951c6300SRichard Henderson 
17729e821eabSRichard Henderson                                         /* arg = abcdefgh */
17739e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
17749e821eabSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .abcdefg */
17759e821eabSRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .b.d.f.h */
17769e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .a.c.e.g */
17779e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = b.d.f.h. */
17789e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = badcfehg */
1779951c6300SRichard Henderson 
17809e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
17819e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ..badcfe */
17829e821eabSRichard Henderson         tcg_gen_and_i64(t1, ret, t2);   /*  t1 = ..dc..hg */
17839e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = ..ba..fe */
17849e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 16);   /*  t1 = dc..hg.. */
17859e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = dcbahgfe */
1786951c6300SRichard Henderson 
17879e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 32);  /*  t0 = ....dcba */
17889e821eabSRichard Henderson         tcg_gen_shli_i64(t1, ret, 32);  /*  t1 = hgfe.... */
17899e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = hgfedcba */
1790951c6300SRichard Henderson 
1791951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1792951c6300SRichard Henderson         tcg_temp_free_i64(t1);
17939e821eabSRichard Henderson         tcg_temp_free_i64(t2);
1794951c6300SRichard Henderson     }
1795951c6300SRichard Henderson }
1796951c6300SRichard Henderson 
1797951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1798951c6300SRichard Henderson {
17993a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18003a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
18013a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
18023a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1803951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1804951c6300SRichard Henderson     } else {
1805951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1806951c6300SRichard Henderson     }
1807951c6300SRichard Henderson }
1808951c6300SRichard Henderson 
1809951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1810951c6300SRichard Henderson {
18113a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18123a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18133a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18143a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1815951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1816951c6300SRichard Henderson     } else {
1817951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1818951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1819951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1820951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1821951c6300SRichard Henderson     }
1822951c6300SRichard Henderson }
1823951c6300SRichard Henderson 
1824951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1825951c6300SRichard Henderson {
18263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18273a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18283a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18293a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1830951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1831951c6300SRichard Henderson     } else {
1832951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1833951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1834951c6300SRichard Henderson     }
1835951c6300SRichard Henderson }
1836951c6300SRichard Henderson 
1837951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1838951c6300SRichard Henderson {
18393a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18403a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18413a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18423a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1843951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1844951c6300SRichard Henderson     } else {
1845951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1846951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1847951c6300SRichard Henderson     }
1848951c6300SRichard Henderson }
1849951c6300SRichard Henderson 
1850951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1851951c6300SRichard Henderson {
18523a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18533a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18543a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18553a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1856951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1857951c6300SRichard Henderson     } else {
1858951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1859951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1860951c6300SRichard Henderson     }
1861951c6300SRichard Henderson }
1862951c6300SRichard Henderson 
1863951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1864951c6300SRichard Henderson {
18653a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18663a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18673a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18683a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1869951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1870951c6300SRichard Henderson     } else {
1871951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1872951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1873951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1874951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1875951c6300SRichard Henderson     }
1876951c6300SRichard Henderson }
1877951c6300SRichard Henderson 
18780e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18790e28d006SRichard Henderson {
18800e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
18810e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
18820e28d006SRichard Henderson     } else {
18830e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
18840e28d006SRichard Henderson     }
18850e28d006SRichard Henderson }
18860e28d006SRichard Henderson 
18870e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18880e28d006SRichard Henderson {
18890e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18900e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
18910e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
189211d11d61SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
189311d11d61SRichard Henderson         tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32);
18940e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
18950e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
18960e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18970e28d006SRichard Henderson         tcg_temp_free_i32(t);
18980e28d006SRichard Henderson     } else {
189911d11d61SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
190011d11d61SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t0);
190111d11d61SRichard Henderson         tcg_temp_free_i64(t0);
19020e28d006SRichard Henderson     }
19030e28d006SRichard Henderson }
19040e28d006SRichard Henderson 
19050e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
19060e28d006SRichard Henderson {
19070e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
19080e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
190914e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
191014e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
191114e99210SRichard Henderson 
191214e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
191314e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
191414e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
191514e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
191614e99210SRichard Henderson         } else {
191714e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
191814e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
191914e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
192014e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
192114e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
192214e99210SRichard Henderson         }
192311d11d61SRichard Henderson         z = tcg_constant_i64(0);
192414e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
192514e99210SRichard Henderson         tcg_temp_free_i64(t);
192614e99210SRichard Henderson         tcg_temp_free_i64(z);
19270e28d006SRichard Henderson     } else {
19280e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
19290e28d006SRichard Henderson     }
19300e28d006SRichard Henderson }
19310e28d006SRichard Henderson 
19320e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
19330e28d006SRichard Henderson {
19340e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
19350e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
19360e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
193711d11d61SRichard Henderson         TCGv_i32 t32 = tcg_temp_new_i32();
193811d11d61SRichard Henderson         tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32);
19390e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
19400e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
19410e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
19420e28d006SRichard Henderson         tcg_temp_free_i32(t32);
194314e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
194414e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
194514e99210SRichard Henderson                && arg2 == 64) {
194614e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
194714e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
194814e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
194914e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
195014e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
195114e99210SRichard Henderson         tcg_temp_free_i64(t);
19520e28d006SRichard Henderson     } else {
195311d11d61SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
195411d11d61SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t0);
195511d11d61SRichard Henderson         tcg_temp_free_i64(t0);
19560e28d006SRichard Henderson     }
19570e28d006SRichard Henderson }
19580e28d006SRichard Henderson 
1959086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
1960086920c2SRichard Henderson {
1961086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
1962086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1963086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
1964086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
1965086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
1966086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
1967086920c2SRichard Henderson         tcg_temp_free_i64(t);
1968086920c2SRichard Henderson     } else {
1969086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
1970086920c2SRichard Henderson     }
1971086920c2SRichard Henderson }
1972086920c2SRichard Henderson 
1973a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
1974a768e4e9SRichard Henderson {
1975a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
1976a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
1977a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
1978a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1979a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1980a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
1981a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1982a768e4e9SRichard Henderson     } else {
1983a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
1984a768e4e9SRichard Henderson     }
1985a768e4e9SRichard Henderson }
1986a768e4e9SRichard Henderson 
1987951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1988951c6300SRichard Henderson {
1989951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1990951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1991951c6300SRichard Henderson     } else {
1992951c6300SRichard Henderson         TCGv_i64 t0, t1;
1993951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1994951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1995951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1996951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1997951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1998951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1999951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2000951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2001951c6300SRichard Henderson     }
2002951c6300SRichard Henderson }
2003951c6300SRichard Henderson 
200407dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2005951c6300SRichard Henderson {
200607dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2007951c6300SRichard Henderson     /* some cases can be optimized here */
2008951c6300SRichard Henderson     if (arg2 == 0) {
2009951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2010951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
201111d11d61SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2));
2012951c6300SRichard Henderson     } else {
2013951c6300SRichard Henderson         TCGv_i64 t0, t1;
2014951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2015951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2016951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
2017951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
2018951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2019951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2020951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2021951c6300SRichard Henderson     }
2022951c6300SRichard Henderson }
2023951c6300SRichard Henderson 
2024951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
2025951c6300SRichard Henderson {
2026951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
2027951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
2028951c6300SRichard Henderson     } else {
2029951c6300SRichard Henderson         TCGv_i64 t0, t1;
2030951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
2031951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
2032951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
2033951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
2034951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
2035951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
2036951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2037951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2038951c6300SRichard Henderson     }
2039951c6300SRichard Henderson }
2040951c6300SRichard Henderson 
204107dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2042951c6300SRichard Henderson {
204307dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2044951c6300SRichard Henderson     /* some cases can be optimized here */
2045951c6300SRichard Henderson     if (arg2 == 0) {
2046951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2047951c6300SRichard Henderson     } else {
2048951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
2049951c6300SRichard Henderson     }
2050951c6300SRichard Henderson }
2051951c6300SRichard Henderson 
2052951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
2053951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
2054951c6300SRichard Henderson {
2055951c6300SRichard Henderson     uint64_t mask;
2056951c6300SRichard Henderson     TCGv_i64 t1;
2057951c6300SRichard Henderson 
2058951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
20590d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2060951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2061951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2062951c6300SRichard Henderson 
20630d0d309dSRichard Henderson     if (len == 64) {
2064951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2065951c6300SRichard Henderson         return;
2066951c6300SRichard Henderson     }
2067951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2068951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2069951c6300SRichard Henderson         return;
2070951c6300SRichard Henderson     }
2071951c6300SRichard Henderson 
20723a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2073951c6300SRichard Henderson         if (ofs >= 32) {
2074951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2075951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2076951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2077951c6300SRichard Henderson             return;
2078951c6300SRichard Henderson         }
2079951c6300SRichard Henderson         if (ofs + len <= 32) {
2080951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2081951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2082951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2083951c6300SRichard Henderson             return;
2084951c6300SRichard Henderson         }
20853a13c3f3SRichard Henderson     }
2086951c6300SRichard Henderson 
2087951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2088951c6300SRichard Henderson 
2089b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i64) {
2090b0a60567SRichard Henderson         if (ofs + len == 64) {
2091b0a60567SRichard Henderson             tcg_gen_shli_i64(t1, arg1, len);
2092b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, t1, arg2, len);
2093b0a60567SRichard Henderson             goto done;
2094b0a60567SRichard Henderson         }
2095b0a60567SRichard Henderson         if (ofs == 0) {
2096b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, arg1, arg2, len);
2097b0a60567SRichard Henderson             tcg_gen_rotli_i64(ret, ret, len);
2098b0a60567SRichard Henderson             goto done;
2099b0a60567SRichard Henderson         }
2100b0a60567SRichard Henderson     }
2101b0a60567SRichard Henderson 
2102b0a60567SRichard Henderson     mask = (1ull << len) - 1;
2103951c6300SRichard Henderson     if (ofs + len < 64) {
2104951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2105951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2106951c6300SRichard Henderson     } else {
2107951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2108951c6300SRichard Henderson     }
2109951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2110951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2111b0a60567SRichard Henderson  done:
2112951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2113951c6300SRichard Henderson }
2114951c6300SRichard Henderson 
211507cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
211607cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
211707cc68d5SRichard Henderson {
211807cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
211907cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
212007cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
212107cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
212207cc68d5SRichard Henderson 
212307cc68d5SRichard Henderson     if (ofs + len == 64) {
212407cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
212507cc68d5SRichard Henderson     } else if (ofs == 0) {
212607cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
212707cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
212807cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
212911d11d61SRichard Henderson         TCGv_i64 zero = tcg_constant_i64(0);
213007cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
213107cc68d5SRichard Henderson     } else {
213207cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
213307cc68d5SRichard Henderson             if (ofs >= 32) {
213407cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
213507cc68d5SRichard Henderson                                       ofs - 32, len);
213607cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
213707cc68d5SRichard Henderson                 return;
213807cc68d5SRichard Henderson             }
213907cc68d5SRichard Henderson             if (ofs + len <= 32) {
214007cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
214107cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
214207cc68d5SRichard Henderson                 return;
214307cc68d5SRichard Henderson             }
214407cc68d5SRichard Henderson         }
214507cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
214607cc68d5SRichard Henderson            which allows ARG to stay live.  */
214707cc68d5SRichard Henderson         switch (len) {
214807cc68d5SRichard Henderson         case 32:
214907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
215007cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
215107cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
215207cc68d5SRichard Henderson                 return;
215307cc68d5SRichard Henderson             }
215407cc68d5SRichard Henderson             break;
215507cc68d5SRichard Henderson         case 16:
215607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
215707cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
215807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
215907cc68d5SRichard Henderson                 return;
216007cc68d5SRichard Henderson             }
216107cc68d5SRichard Henderson             break;
216207cc68d5SRichard Henderson         case 8:
216307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
216407cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
216507cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
216607cc68d5SRichard Henderson                 return;
216707cc68d5SRichard Henderson             }
216807cc68d5SRichard Henderson             break;
216907cc68d5SRichard Henderson         }
217007cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
217107cc68d5SRichard Henderson         switch (ofs + len) {
217207cc68d5SRichard Henderson         case 32:
217307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
217407cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
217507cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
217607cc68d5SRichard Henderson                 return;
217707cc68d5SRichard Henderson             }
217807cc68d5SRichard Henderson             break;
217907cc68d5SRichard Henderson         case 16:
218007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
218107cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
218207cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
218307cc68d5SRichard Henderson                 return;
218407cc68d5SRichard Henderson             }
218507cc68d5SRichard Henderson             break;
218607cc68d5SRichard Henderson         case 8:
218707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
218807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
218907cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
219007cc68d5SRichard Henderson                 return;
219107cc68d5SRichard Henderson             }
219207cc68d5SRichard Henderson             break;
219307cc68d5SRichard Henderson         }
219407cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
219507cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
219607cc68d5SRichard Henderson     }
219707cc68d5SRichard Henderson }
219807cc68d5SRichard Henderson 
21997ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
22007ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
22017ec8bab3SRichard Henderson {
22027ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22037ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22047ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22057ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22067ec8bab3SRichard Henderson 
22077ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
22087ec8bab3SRichard Henderson     if (ofs + len == 64) {
22097ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
22107ec8bab3SRichard Henderson         return;
22117ec8bab3SRichard Henderson     }
22127ec8bab3SRichard Henderson     if (ofs == 0) {
22137ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
22147ec8bab3SRichard Henderson         return;
22157ec8bab3SRichard Henderson     }
22167ec8bab3SRichard Henderson 
22177ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22187ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22197ec8bab3SRichard Henderson         if (ofs >= 32) {
22207ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22217ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22227ec8bab3SRichard Henderson             return;
22237ec8bab3SRichard Henderson         }
22247ec8bab3SRichard Henderson         if (ofs + len <= 32) {
22257ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22267ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
22277ec8bab3SRichard Henderson             return;
22287ec8bab3SRichard Henderson         }
22297ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
22307ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
22317ec8bab3SRichard Henderson         goto do_shift_and;
22327ec8bab3SRichard Henderson     }
22337ec8bab3SRichard Henderson 
22347ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
22357ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22367ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
22377ec8bab3SRichard Henderson         return;
22387ec8bab3SRichard Henderson     }
22397ec8bab3SRichard Henderson 
22407ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
22417ec8bab3SRichard Henderson     switch (ofs + len) {
22427ec8bab3SRichard Henderson     case 32:
22437ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
22447ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
22457ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22467ec8bab3SRichard Henderson             return;
22477ec8bab3SRichard Henderson         }
22487ec8bab3SRichard Henderson         break;
22497ec8bab3SRichard Henderson     case 16:
22507ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
22517ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
22527ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22537ec8bab3SRichard Henderson             return;
22547ec8bab3SRichard Henderson         }
22557ec8bab3SRichard Henderson         break;
22567ec8bab3SRichard Henderson     case 8:
22577ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
22587ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
22597ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22607ec8bab3SRichard Henderson             return;
22617ec8bab3SRichard Henderson         }
22627ec8bab3SRichard Henderson         break;
22637ec8bab3SRichard Henderson     }
22647ec8bab3SRichard Henderson 
22657ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
22667ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
22677ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
22687ec8bab3SRichard Henderson     switch (len) {
22697ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
22707ec8bab3SRichard Henderson     do_shift_and:
22717ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
22727ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
22737ec8bab3SRichard Henderson         break;
22747ec8bab3SRichard Henderson     default:
22757ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
22767ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
22777ec8bab3SRichard Henderson         break;
22787ec8bab3SRichard Henderson     }
22797ec8bab3SRichard Henderson }
22807ec8bab3SRichard Henderson 
22817ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
22827ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
22837ec8bab3SRichard Henderson {
22847ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22857ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22867ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22877ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22887ec8bab3SRichard Henderson 
22897ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
22907ec8bab3SRichard Henderson     if (ofs + len == 64) {
22917ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
22927ec8bab3SRichard Henderson         return;
22937ec8bab3SRichard Henderson     }
22947ec8bab3SRichard Henderson     if (ofs == 0) {
22957ec8bab3SRichard Henderson         switch (len) {
22967ec8bab3SRichard Henderson         case 32:
22977ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22987ec8bab3SRichard Henderson             return;
22997ec8bab3SRichard Henderson         case 16:
23007ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23017ec8bab3SRichard Henderson             return;
23027ec8bab3SRichard Henderson         case 8:
23037ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23047ec8bab3SRichard Henderson             return;
23057ec8bab3SRichard Henderson         }
23067ec8bab3SRichard Henderson     }
23077ec8bab3SRichard Henderson 
23087ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
23097ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
23107ec8bab3SRichard Henderson         if (ofs >= 32) {
23117ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
23127ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
23137ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
23147ec8bab3SRichard Henderson         } else if (ofs == 0) {
23157ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
23167ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
23177ec8bab3SRichard Henderson             return;
23187ec8bab3SRichard Henderson         } else if (len > 32) {
23197ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
23207ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
23217ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
23227ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
23237ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23247ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
23257ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
23267ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
23277ec8bab3SRichard Henderson             return;
23287ec8bab3SRichard Henderson         } else {
23297ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
23307ec8bab3SRichard Henderson                field sits at the MSB.  */
23317ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
23327ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
23337ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
23347ec8bab3SRichard Henderson         }
23357ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
23367ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
23377ec8bab3SRichard Henderson         return;
23387ec8bab3SRichard Henderson     }
23397ec8bab3SRichard Henderson 
23407ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
23417ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
23427ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
23437ec8bab3SRichard Henderson         return;
23447ec8bab3SRichard Henderson     }
23457ec8bab3SRichard Henderson 
23467ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
23477ec8bab3SRichard Henderson     switch (ofs + len) {
23487ec8bab3SRichard Henderson     case 32:
23497ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23507ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
23517ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23527ec8bab3SRichard Henderson             return;
23537ec8bab3SRichard Henderson         }
23547ec8bab3SRichard Henderson         break;
23557ec8bab3SRichard Henderson     case 16:
23567ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23577ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23587ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23597ec8bab3SRichard Henderson             return;
23607ec8bab3SRichard Henderson         }
23617ec8bab3SRichard Henderson         break;
23627ec8bab3SRichard Henderson     case 8:
23637ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23647ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23657ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23667ec8bab3SRichard Henderson             return;
23677ec8bab3SRichard Henderson         }
23687ec8bab3SRichard Henderson         break;
23697ec8bab3SRichard Henderson     }
23707ec8bab3SRichard Henderson     switch (len) {
23717ec8bab3SRichard Henderson     case 32:
23727ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23737ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23747ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
23757ec8bab3SRichard Henderson             return;
23767ec8bab3SRichard Henderson         }
23777ec8bab3SRichard Henderson         break;
23787ec8bab3SRichard Henderson     case 16:
23797ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23807ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23817ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
23827ec8bab3SRichard Henderson             return;
23837ec8bab3SRichard Henderson         }
23847ec8bab3SRichard Henderson         break;
23857ec8bab3SRichard Henderson     case 8:
23867ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23877ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23887ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
23897ec8bab3SRichard Henderson             return;
23907ec8bab3SRichard Henderson         }
23917ec8bab3SRichard Henderson         break;
23927ec8bab3SRichard Henderson     }
23937ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23947ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
23957ec8bab3SRichard Henderson }
23967ec8bab3SRichard Henderson 
23972089fcc9SDavid Hildenbrand /*
23982089fcc9SDavid Hildenbrand  * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
23992089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
24002089fcc9SDavid Hildenbrand  */
24012089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
24022089fcc9SDavid Hildenbrand                           unsigned int ofs)
24032089fcc9SDavid Hildenbrand {
24042089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 64);
24052089fcc9SDavid Hildenbrand     if (ofs == 0) {
24062089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, al);
24072089fcc9SDavid Hildenbrand     } else if (ofs == 64) {
24082089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, ah);
24092089fcc9SDavid Hildenbrand     } else if (al == ah) {
24102089fcc9SDavid Hildenbrand         tcg_gen_rotri_i64(ret, al, ofs);
2411fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i64) {
2412fce1296fSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
24132089fcc9SDavid Hildenbrand     } else {
24142089fcc9SDavid Hildenbrand         TCGv_i64 t0 = tcg_temp_new_i64();
24152089fcc9SDavid Hildenbrand         tcg_gen_shri_i64(t0, al, ofs);
24162089fcc9SDavid Hildenbrand         tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs);
24172089fcc9SDavid Hildenbrand         tcg_temp_free_i64(t0);
24182089fcc9SDavid Hildenbrand     }
24192089fcc9SDavid Hildenbrand }
24202089fcc9SDavid Hildenbrand 
2421951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2422951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2423951c6300SRichard Henderson {
242437ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
242537ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
242637ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
242737ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
242837ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2429951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2430951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2431951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2432951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2433951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2434951c6300SRichard Henderson 
2435951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2436951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2437951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2438951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2439951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2440951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2441951c6300SRichard Henderson         } else {
2442951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2443951c6300SRichard Henderson 
2444951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2445951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2446951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2447951c6300SRichard Henderson 
2448951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2449951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2450951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2451951c6300SRichard Henderson         }
2452951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2453951c6300SRichard Henderson         tcg_temp_free_i32(t1);
24543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2455951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2456951c6300SRichard Henderson     } else {
2457951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2458951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2459951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2460951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2461951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2462951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2463951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2464951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2465951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2466951c6300SRichard Henderson     }
2467951c6300SRichard Henderson }
2468951c6300SRichard Henderson 
2469951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2470951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2471951c6300SRichard Henderson {
2472951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2473951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2474951c6300SRichard Henderson     } else {
2475951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2476951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2477951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2478951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2479951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2480951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2481951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2482951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2483951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2484951c6300SRichard Henderson     }
2485951c6300SRichard Henderson }
2486951c6300SRichard Henderson 
2487951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2488951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2489951c6300SRichard Henderson {
2490951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2491951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2492951c6300SRichard Henderson     } else {
2493951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2494951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2495951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2496951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2497951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2498951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2499951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2500951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2501951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2502951c6300SRichard Henderson     }
2503951c6300SRichard Henderson }
2504951c6300SRichard Henderson 
2505951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2506951c6300SRichard Henderson {
2507951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2508951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2509951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2510951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2511951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2512951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2513951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2514951c6300SRichard Henderson         tcg_temp_free_i64(t);
2515951c6300SRichard Henderson     } else {
2516951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2517951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2518951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2519951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2520951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2521951c6300SRichard Henderson     }
2522951c6300SRichard Henderson }
2523951c6300SRichard Henderson 
2524951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2525951c6300SRichard Henderson {
2526951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2527951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2528951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2529951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2530951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2531951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2532951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2533951c6300SRichard Henderson         tcg_temp_free_i64(t);
2534951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2535951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2536951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2537951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2538951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2539951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2540951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2541951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2542951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2543951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2544951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2545951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2546951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2547951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2548951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2549951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2550951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2551951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2552951c6300SRichard Henderson     } else {
2553951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2554951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2555951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2556951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2557951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2558951c6300SRichard Henderson     }
2559951c6300SRichard Henderson }
2560951c6300SRichard Henderson 
25615087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
25625087abfbSRichard Henderson {
25635087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
25645087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
25655087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
25665087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
25675087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
25685087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
25695087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
25705087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
25715087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
25725087abfbSRichard Henderson     tcg_temp_free_i64(t0);
25735087abfbSRichard Henderson     tcg_temp_free_i64(t1);
25745087abfbSRichard Henderson     tcg_temp_free_i64(t2);
25755087abfbSRichard Henderson }
25765087abfbSRichard Henderson 
2577b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2578b87fb8cdSRichard Henderson {
2579b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2580b87fb8cdSRichard Henderson }
2581b87fb8cdSRichard Henderson 
2582b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2583b87fb8cdSRichard Henderson {
2584b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2585b87fb8cdSRichard Henderson }
2586b87fb8cdSRichard Henderson 
2587b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2588b87fb8cdSRichard Henderson {
2589b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2590b87fb8cdSRichard Henderson }
2591b87fb8cdSRichard Henderson 
2592b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2593b87fb8cdSRichard Henderson {
2594b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2595b87fb8cdSRichard Henderson }
2596b87fb8cdSRichard Henderson 
2597ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
2598ff1f11f7SRichard Henderson {
2599ff1f11f7SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
2600ff1f11f7SRichard Henderson 
2601ff1f11f7SRichard Henderson     tcg_gen_sari_i64(t, a, 63);
2602ff1f11f7SRichard Henderson     tcg_gen_xor_i64(ret, a, t);
2603ff1f11f7SRichard Henderson     tcg_gen_sub_i64(ret, ret, t);
2604ff1f11f7SRichard Henderson     tcg_temp_free_i64(t);
2605ff1f11f7SRichard Henderson }
2606ff1f11f7SRichard Henderson 
2607951c6300SRichard Henderson /* Size changing operations.  */
2608951c6300SRichard Henderson 
2609609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2610951c6300SRichard Henderson {
26113a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2612951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2613609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2614b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2615ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2616951c6300SRichard Henderson     } else {
2617dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2618609ad705SRichard Henderson     }
2619609ad705SRichard Henderson }
2620609ad705SRichard Henderson 
2621609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2622609ad705SRichard Henderson {
2623609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2624609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2625609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2626b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2627ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2628951c6300SRichard Henderson     } else {
2629951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2630609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2631dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2632951c6300SRichard Henderson         tcg_temp_free_i64(t);
2633951c6300SRichard Henderson     }
2634951c6300SRichard Henderson }
2635951c6300SRichard Henderson 
2636951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2637951c6300SRichard Henderson {
26383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2639951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2640951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
26413a13c3f3SRichard Henderson     } else {
2642b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2643ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26443a13c3f3SRichard Henderson     }
2645951c6300SRichard Henderson }
2646951c6300SRichard Henderson 
2647951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2648951c6300SRichard Henderson {
26493a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2650951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2651951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
26523a13c3f3SRichard Henderson     } else {
2653b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2654ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26553a13c3f3SRichard Henderson     }
2656951c6300SRichard Henderson }
2657951c6300SRichard Henderson 
2658951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2659951c6300SRichard Henderson {
26603a13c3f3SRichard Henderson     TCGv_i64 tmp;
26613a13c3f3SRichard Henderson 
26623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2663951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2664951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
26653a13c3f3SRichard Henderson         return;
26663a13c3f3SRichard Henderson     }
26673a13c3f3SRichard Henderson 
26683a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2669951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2670951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2671951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2672951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2673951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2674951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2675951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2676951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2677951c6300SRichard Henderson     } else {
2678951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2679951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2680951c6300SRichard Henderson     }
2681951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2682951c6300SRichard Henderson }
2683951c6300SRichard Henderson 
2684951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2685951c6300SRichard Henderson {
26863a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2687951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2688951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
26893a13c3f3SRichard Henderson     } else {
2690609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2691609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
26923a13c3f3SRichard Henderson     }
2693951c6300SRichard Henderson }
2694951c6300SRichard Henderson 
2695951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2696951c6300SRichard Henderson {
2697951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2698951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2699951c6300SRichard Henderson }
2700951c6300SRichard Henderson 
2701951c6300SRichard Henderson /* QEMU specific operations.  */
2702951c6300SRichard Henderson 
2703d9971435SRichard Henderson void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
270407ea28b4SRichard Henderson {
2705eba40358SRichard Henderson     /*
2706eba40358SRichard Henderson      * Let the jit code return the read-only version of the
2707eba40358SRichard Henderson      * TranslationBlock, so that we minimize the pc-relative
2708eba40358SRichard Henderson      * distance of the address of the exit_tb code to TB.
2709eba40358SRichard Henderson      * This will improve utilization of pc-relative address loads.
2710eba40358SRichard Henderson      *
2711eba40358SRichard Henderson      * TODO: Move this to translator_loop, so that all const
2712eba40358SRichard Henderson      * TranslationBlock pointers refer to read-only memory.
2713eba40358SRichard Henderson      * This requires coordination with targets that do not use
2714eba40358SRichard Henderson      * the translator_loop.
2715eba40358SRichard Henderson      */
2716eba40358SRichard Henderson     uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx;
271707ea28b4SRichard Henderson 
271807ea28b4SRichard Henderson     if (tb == NULL) {
271907ea28b4SRichard Henderson         tcg_debug_assert(idx == 0);
272007ea28b4SRichard Henderson     } else if (idx <= TB_EXIT_IDXMAX) {
272107ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG
272207ea28b4SRichard Henderson         /* This is an exit following a goto_tb.  Verify that we have
272307ea28b4SRichard Henderson            seen this numbered exit before, via tcg_gen_goto_tb.  */
272407ea28b4SRichard Henderson         tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
272507ea28b4SRichard Henderson #endif
272607ea28b4SRichard Henderson     } else {
272707ea28b4SRichard Henderson         /* This is an exit via the exitreq label.  */
272807ea28b4SRichard Henderson         tcg_debug_assert(idx == TB_EXIT_REQUESTED);
272907ea28b4SRichard Henderson     }
273007ea28b4SRichard Henderson 
2731e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
273207ea28b4SRichard Henderson     tcg_gen_op1i(INDEX_op_exit_tb, val);
273307ea28b4SRichard Henderson }
273407ea28b4SRichard Henderson 
2735951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2736951c6300SRichard Henderson {
273784f15616SRichard Henderson     /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
273884f15616SRichard Henderson     tcg_debug_assert(!(tcg_ctx->tb_cflags & CF_NO_GOTO_TB));
2739951c6300SRichard Henderson     /* We only support two chained exits.  */
274007ea28b4SRichard Henderson     tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
2741951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2742a4761232SPhilippe Mathieu-Daudé     /* Verify that we haven't seen this numbered exit before.  */
2743b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2744b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2745951c6300SRichard Henderson #endif
2746e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2747951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2748951c6300SRichard Henderson }
2749951c6300SRichard Henderson 
27507f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2751cedbcb01SEmilio G. Cota {
2752e6d86bedSEmilio G. Cota     TCGv_ptr ptr;
2753e6d86bedSEmilio G. Cota 
275484f15616SRichard Henderson     if (tcg_ctx->tb_cflags & CF_NO_GOTO_PTR) {
275584f15616SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
275684f15616SRichard Henderson         return;
275784f15616SRichard Henderson     }
275884f15616SRichard Henderson 
2759e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2760e6d86bedSEmilio G. Cota     ptr = tcg_temp_new_ptr();
27611c2adb95SRichard Henderson     gen_helper_lookup_tb_ptr(ptr, cpu_env);
2762ae8b75dcSRichard Henderson     tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2763cedbcb01SEmilio G. Cota     tcg_temp_free_ptr(ptr);
2764cedbcb01SEmilio G. Cota }
2765cedbcb01SEmilio G. Cota 
276614776ab5STony Nguyen static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
2767951c6300SRichard Henderson {
27681f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
27691f00b27fSSergey Sorokin     (void)get_alignment_bits(op);
27701f00b27fSSergey Sorokin 
2771951c6300SRichard Henderson     switch (op & MO_SIZE) {
2772951c6300SRichard Henderson     case MO_8:
2773951c6300SRichard Henderson         op &= ~MO_BSWAP;
2774951c6300SRichard Henderson         break;
2775951c6300SRichard Henderson     case MO_16:
2776951c6300SRichard Henderson         break;
2777951c6300SRichard Henderson     case MO_32:
2778951c6300SRichard Henderson         if (!is64) {
2779951c6300SRichard Henderson             op &= ~MO_SIGN;
2780951c6300SRichard Henderson         }
2781951c6300SRichard Henderson         break;
2782951c6300SRichard Henderson     case MO_64:
2783*4b473e0cSRichard Henderson         if (is64) {
2784*4b473e0cSRichard Henderson             op &= ~MO_SIGN;
2785951c6300SRichard Henderson             break;
2786951c6300SRichard Henderson         }
2787*4b473e0cSRichard Henderson         /* fall through */
2788*4b473e0cSRichard Henderson     default:
2789*4b473e0cSRichard Henderson         g_assert_not_reached();
2790*4b473e0cSRichard Henderson     }
2791951c6300SRichard Henderson     if (st) {
2792951c6300SRichard Henderson         op &= ~MO_SIGN;
2793951c6300SRichard Henderson     }
2794951c6300SRichard Henderson     return op;
2795951c6300SRichard Henderson }
2796951c6300SRichard Henderson 
2797c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
279814776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2799951c6300SRichard Henderson {
280059227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2801951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
280259227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2803951c6300SRichard Henderson #else
2804c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
280559227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2806c45cb8bbSRichard Henderson     } else {
2807ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2808c45cb8bbSRichard Henderson     }
2809951c6300SRichard Henderson #endif
2810c45cb8bbSRichard Henderson }
2811c45cb8bbSRichard Henderson 
2812c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
281314776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2814c45cb8bbSRichard Henderson {
281559227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2816c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2817c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
281859227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2819c45cb8bbSRichard Henderson     } else {
2820ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2821c45cb8bbSRichard Henderson     }
2822c45cb8bbSRichard Henderson #else
2823c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
282459227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
282559227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2826c45cb8bbSRichard Henderson     } else {
282759227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2828c45cb8bbSRichard Henderson     }
2829c45cb8bbSRichard Henderson #endif
2830c45cb8bbSRichard Henderson }
2831951c6300SRichard Henderson 
2832b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2833b32dc337SPranith Kumar {
2834b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2835b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2836b32dc337SPranith Kumar #endif
2837b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2838b32dc337SPranith Kumar     if (type) {
2839b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2840b32dc337SPranith Kumar     }
2841b32dc337SPranith Kumar }
2842b32dc337SPranith Kumar 
2843fcc54ab5SAlex Bennée static inline TCGv plugin_prep_mem_callbacks(TCGv vaddr)
2844fcc54ab5SAlex Bennée {
2845fcc54ab5SAlex Bennée #ifdef CONFIG_PLUGIN
2846fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
2847fcc54ab5SAlex Bennée         /* Save a copy of the vaddr for use after a load.  */
2848fcc54ab5SAlex Bennée         TCGv temp = tcg_temp_new();
2849fcc54ab5SAlex Bennée         tcg_gen_mov_tl(temp, vaddr);
2850fcc54ab5SAlex Bennée         return temp;
2851fcc54ab5SAlex Bennée     }
2852fcc54ab5SAlex Bennée #endif
2853fcc54ab5SAlex Bennée     return vaddr;
2854fcc54ab5SAlex Bennée }
2855fcc54ab5SAlex Bennée 
2856e6d86bedSEmilio G. Cota static inline void plugin_gen_mem_callbacks(TCGv vaddr, uint16_t info)
2857e6d86bedSEmilio G. Cota {
2858e6d86bedSEmilio G. Cota #ifdef CONFIG_PLUGIN
2859fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
2860e6d86bedSEmilio G. Cota         plugin_gen_empty_mem_callback(vaddr, info);
2861fcc54ab5SAlex Bennée         tcg_temp_free(vaddr);
2862fcc54ab5SAlex Bennée     }
2863e6d86bedSEmilio G. Cota #endif
2864e6d86bedSEmilio G. Cota }
2865e6d86bedSEmilio G. Cota 
286614776ab5STony Nguyen void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2867951c6300SRichard Henderson {
286814776ab5STony Nguyen     MemOp orig_memop;
2869e6d86bedSEmilio G. Cota     uint16_t info = trace_mem_get_info(memop, idx, 0);
2870e1dcf352SRichard Henderson 
2871b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2872951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2873e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2874e1dcf352SRichard Henderson 
2875e1dcf352SRichard Henderson     orig_memop = memop;
2876e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2877e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2878359feba5SRichard Henderson         /* The bswap primitive benefits from zero-extended input.  */
2879e1dcf352SRichard Henderson         if ((memop & MO_SSIZE) == MO_SW) {
2880e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2881e1dcf352SRichard Henderson         }
2882e1dcf352SRichard Henderson     }
2883e1dcf352SRichard Henderson 
2884fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2885c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
2886e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2887e1dcf352SRichard Henderson 
2888e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2889e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2890e1dcf352SRichard Henderson         case MO_16:
2891359feba5SRichard Henderson             tcg_gen_bswap16_i32(val, val, (orig_memop & MO_SIGN
2892359feba5SRichard Henderson                                            ? TCG_BSWAP_IZ | TCG_BSWAP_OS
2893359feba5SRichard Henderson                                            : TCG_BSWAP_IZ | TCG_BSWAP_OZ));
2894e1dcf352SRichard Henderson             break;
2895e1dcf352SRichard Henderson         case MO_32:
2896e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(val, val);
2897e1dcf352SRichard Henderson             break;
2898e1dcf352SRichard Henderson         default:
2899e1dcf352SRichard Henderson             g_assert_not_reached();
2900e1dcf352SRichard Henderson         }
2901e1dcf352SRichard Henderson     }
2902951c6300SRichard Henderson }
2903951c6300SRichard Henderson 
290414776ab5STony Nguyen void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2905951c6300SRichard Henderson {
2906e1dcf352SRichard Henderson     TCGv_i32 swap = NULL;
2907e6d86bedSEmilio G. Cota     uint16_t info = trace_mem_get_info(memop, idx, 1);
2908e1dcf352SRichard Henderson 
2909b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2910951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
2911e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2912e1dcf352SRichard Henderson 
2913e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2914e1dcf352SRichard Henderson         swap = tcg_temp_new_i32();
2915e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
2916e1dcf352SRichard Henderson         case MO_16:
2917b53357acSRichard Henderson             tcg_gen_bswap16_i32(swap, val, 0);
2918e1dcf352SRichard Henderson             break;
2919e1dcf352SRichard Henderson         case MO_32:
2920e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(swap, val);
2921e1dcf352SRichard Henderson             break;
2922e1dcf352SRichard Henderson         default:
2923e1dcf352SRichard Henderson             g_assert_not_reached();
2924e1dcf352SRichard Henderson         }
2925e1dcf352SRichard Henderson         val = swap;
2926e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2927e1dcf352SRichard Henderson     }
2928e1dcf352SRichard Henderson 
2929fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
293007ce0b05SRichard Henderson     if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) {
293107ce0b05SRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx);
293207ce0b05SRichard Henderson     } else {
2933c45cb8bbSRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
293407ce0b05SRichard Henderson     }
2935e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2936e1dcf352SRichard Henderson 
2937e1dcf352SRichard Henderson     if (swap) {
2938e1dcf352SRichard Henderson         tcg_temp_free_i32(swap);
2939e1dcf352SRichard Henderson     }
2940951c6300SRichard Henderson }
2941951c6300SRichard Henderson 
294214776ab5STony Nguyen void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
2943951c6300SRichard Henderson {
294414776ab5STony Nguyen     MemOp orig_memop;
2945e6d86bedSEmilio G. Cota     uint16_t info;
2946e1dcf352SRichard Henderson 
29473a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2948951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
2949951c6300SRichard Henderson         if (memop & MO_SIGN) {
2950951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
2951951c6300SRichard Henderson         } else {
2952951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
2953951c6300SRichard Henderson         }
2954951c6300SRichard Henderson         return;
2955951c6300SRichard Henderson     }
2956951c6300SRichard Henderson 
2957e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2958c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2959e6d86bedSEmilio G. Cota     info = trace_mem_get_info(memop, idx, 0);
2960e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2961e1dcf352SRichard Henderson 
2962e1dcf352SRichard Henderson     orig_memop = memop;
2963e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2964e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2965359feba5SRichard Henderson         /* The bswap primitive benefits from zero-extended input.  */
2966e1dcf352SRichard Henderson         if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
2967e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2968e1dcf352SRichard Henderson         }
2969e1dcf352SRichard Henderson     }
2970e1dcf352SRichard Henderson 
2971fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2972c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
2973e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2974e1dcf352SRichard Henderson 
2975e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2976359feba5SRichard Henderson         int flags = (orig_memop & MO_SIGN
2977359feba5SRichard Henderson                      ? TCG_BSWAP_IZ | TCG_BSWAP_OS
2978359feba5SRichard Henderson                      : TCG_BSWAP_IZ | TCG_BSWAP_OZ);
2979e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2980e1dcf352SRichard Henderson         case MO_16:
2981359feba5SRichard Henderson             tcg_gen_bswap16_i64(val, val, flags);
2982e1dcf352SRichard Henderson             break;
2983e1dcf352SRichard Henderson         case MO_32:
2984359feba5SRichard Henderson             tcg_gen_bswap32_i64(val, val, flags);
2985e1dcf352SRichard Henderson             break;
2986e1dcf352SRichard Henderson         case MO_64:
2987e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(val, val);
2988e1dcf352SRichard Henderson             break;
2989e1dcf352SRichard Henderson         default:
2990e1dcf352SRichard Henderson             g_assert_not_reached();
2991e1dcf352SRichard Henderson         }
2992e1dcf352SRichard Henderson     }
2993951c6300SRichard Henderson }
2994951c6300SRichard Henderson 
299514776ab5STony Nguyen void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
2996951c6300SRichard Henderson {
2997e1dcf352SRichard Henderson     TCGv_i64 swap = NULL;
2998e6d86bedSEmilio G. Cota     uint16_t info;
2999e1dcf352SRichard Henderson 
30003a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
3001951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
3002951c6300SRichard Henderson         return;
3003951c6300SRichard Henderson     }
3004951c6300SRichard Henderson 
3005e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
3006c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
3007e6d86bedSEmilio G. Cota     info = trace_mem_get_info(memop, idx, 1);
3008e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
3009e1dcf352SRichard Henderson 
3010e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
3011e1dcf352SRichard Henderson         swap = tcg_temp_new_i64();
3012e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
3013e1dcf352SRichard Henderson         case MO_16:
3014b53357acSRichard Henderson             tcg_gen_bswap16_i64(swap, val, 0);
3015e1dcf352SRichard Henderson             break;
3016e1dcf352SRichard Henderson         case MO_32:
3017b53357acSRichard Henderson             tcg_gen_bswap32_i64(swap, val, 0);
3018e1dcf352SRichard Henderson             break;
3019e1dcf352SRichard Henderson         case MO_64:
3020e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(swap, val);
3021e1dcf352SRichard Henderson             break;
3022e1dcf352SRichard Henderson         default:
3023e1dcf352SRichard Henderson             g_assert_not_reached();
3024e1dcf352SRichard Henderson         }
3025e1dcf352SRichard Henderson         val = swap;
3026e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
3027e1dcf352SRichard Henderson     }
3028e1dcf352SRichard Henderson 
3029fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
3030c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
3031e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
3032e1dcf352SRichard Henderson 
3033e1dcf352SRichard Henderson     if (swap) {
3034e1dcf352SRichard Henderson         tcg_temp_free_i64(swap);
3035e1dcf352SRichard Henderson     }
3036951c6300SRichard Henderson }
3037c482cb11SRichard Henderson 
303814776ab5STony Nguyen static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
3039c482cb11SRichard Henderson {
3040c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3041c482cb11SRichard Henderson     case MO_SB:
3042c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
3043c482cb11SRichard Henderson         break;
3044c482cb11SRichard Henderson     case MO_UB:
3045c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
3046c482cb11SRichard Henderson         break;
3047c482cb11SRichard Henderson     case MO_SW:
3048c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
3049c482cb11SRichard Henderson         break;
3050c482cb11SRichard Henderson     case MO_UW:
3051c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
3052c482cb11SRichard Henderson         break;
3053c482cb11SRichard Henderson     default:
3054c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
3055c482cb11SRichard Henderson         break;
3056c482cb11SRichard Henderson     }
3057c482cb11SRichard Henderson }
3058c482cb11SRichard Henderson 
305914776ab5STony Nguyen static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
3060c482cb11SRichard Henderson {
3061c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3062c482cb11SRichard Henderson     case MO_SB:
3063c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
3064c482cb11SRichard Henderson         break;
3065c482cb11SRichard Henderson     case MO_UB:
3066c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
3067c482cb11SRichard Henderson         break;
3068c482cb11SRichard Henderson     case MO_SW:
3069c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
3070c482cb11SRichard Henderson         break;
3071c482cb11SRichard Henderson     case MO_UW:
3072c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
3073c482cb11SRichard Henderson         break;
3074c482cb11SRichard Henderson     case MO_SL:
3075c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
3076c482cb11SRichard Henderson         break;
3077c482cb11SRichard Henderson     case MO_UL:
3078c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
3079c482cb11SRichard Henderson         break;
3080c482cb11SRichard Henderson     default:
3081c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
3082c482cb11SRichard Henderson         break;
3083c482cb11SRichard Henderson     }
3084c482cb11SRichard Henderson }
3085c482cb11SRichard Henderson 
3086c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
3087c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
3088c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
3089c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
3090c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
3091c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
3092c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
3093c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
3094c482cb11SRichard Henderson 
3095df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3096df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
3097df79b996SRichard Henderson #else
3098df79b996SRichard Henderson # define WITH_ATOMIC64(X)
3099df79b996SRichard Henderson #endif
3100df79b996SRichard Henderson 
3101*4b473e0cSRichard Henderson static void * const table_cmpxchg[(MO_SIZE | MO_BSWAP) + 1] = {
3102c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
3103c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
3104c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
3105c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
3106c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
3107df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
3108df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
3109c482cb11SRichard Henderson };
3110c482cb11SRichard Henderson 
3111c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
311214776ab5STony Nguyen                                 TCGv_i32 newv, TCGArg idx, MemOp memop)
3113c482cb11SRichard Henderson {
3114c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3115c482cb11SRichard Henderson 
3116b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
3117c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
3118c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
3119c482cb11SRichard Henderson 
3120c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
3121c482cb11SRichard Henderson 
3122c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
3123c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
3124c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3125c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
3126c482cb11SRichard Henderson 
3127c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3128c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
3129c482cb11SRichard Henderson         } else {
3130c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
3131c482cb11SRichard Henderson         }
3132c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
3133c482cb11SRichard Henderson     } else {
3134c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
3135e28a8664SRichard Henderson         TCGMemOpIdx oi;
3136c482cb11SRichard Henderson 
3137c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3138c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3139c482cb11SRichard Henderson 
3140e28a8664SRichard Henderson         oi = make_memop_idx(memop & ~MO_SIGN, idx);
314111d11d61SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3142c482cb11SRichard Henderson 
3143c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3144c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
3145c482cb11SRichard Henderson         }
3146c482cb11SRichard Henderson     }
3147c482cb11SRichard Henderson }
3148c482cb11SRichard Henderson 
3149c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
315014776ab5STony Nguyen                                 TCGv_i64 newv, TCGArg idx, MemOp memop)
3151c482cb11SRichard Henderson {
3152c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3153c482cb11SRichard Henderson 
3154b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
3155c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
3156c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
3157c482cb11SRichard Henderson 
3158c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
3159c482cb11SRichard Henderson 
3160c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
3161c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
3162c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3163c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
3164c482cb11SRichard Henderson 
3165c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3166c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
3167c482cb11SRichard Henderson         } else {
3168c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
3169c482cb11SRichard Henderson         }
3170c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
3171c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
3172df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3173c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
3174e28a8664SRichard Henderson         TCGMemOpIdx oi;
3175c482cb11SRichard Henderson 
3176c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3177c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3178c482cb11SRichard Henderson 
3179e28a8664SRichard Henderson         oi = make_memop_idx(memop, idx);
318011d11d61SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3181df79b996SRichard Henderson #else
31821c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
318379b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
318479b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
318579b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
3186df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3187c482cb11SRichard Henderson     } else {
3188c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
3189c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
3190c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3191c482cb11SRichard Henderson 
3192c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
3193c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
3194c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
3195c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
3196c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
3197c482cb11SRichard Henderson 
3198c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
3199c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3200c482cb11SRichard Henderson 
3201c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3202c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
3203c482cb11SRichard Henderson         }
3204c482cb11SRichard Henderson     }
3205c482cb11SRichard Henderson }
3206c482cb11SRichard Henderson 
3207c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
320814776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3209c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
3210c482cb11SRichard Henderson {
3211c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
3212c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
3213c482cb11SRichard Henderson 
3214c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3215c482cb11SRichard Henderson 
3216852f933eSRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop);
3217852f933eSRichard Henderson     tcg_gen_ext_i32(t2, val, memop);
3218852f933eSRichard Henderson     gen(t2, t1, t2);
3219c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3220c482cb11SRichard Henderson 
3221c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
3222c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
3223c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
3224c482cb11SRichard Henderson }
3225c482cb11SRichard Henderson 
3226c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
322714776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3228c482cb11SRichard Henderson {
3229c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
3230e28a8664SRichard Henderson     TCGMemOpIdx oi;
3231c482cb11SRichard Henderson 
3232c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3233c482cb11SRichard Henderson 
3234c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
3235c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
3236c482cb11SRichard Henderson 
3237e28a8664SRichard Henderson     oi = make_memop_idx(memop & ~MO_SIGN, idx);
323811d11d61SRichard Henderson     gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
3239c482cb11SRichard Henderson 
3240c482cb11SRichard Henderson     if (memop & MO_SIGN) {
3241c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
3242c482cb11SRichard Henderson     }
3243c482cb11SRichard Henderson }
3244c482cb11SRichard Henderson 
3245c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
324614776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3247c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
3248c482cb11SRichard Henderson {
3249c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3250c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3251c482cb11SRichard Henderson 
3252c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3253c482cb11SRichard Henderson 
3254852f933eSRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop);
3255852f933eSRichard Henderson     tcg_gen_ext_i64(t2, val, memop);
3256852f933eSRichard Henderson     gen(t2, t1, t2);
3257c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3258c482cb11SRichard Henderson 
3259c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
3260c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
3261c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
3262c482cb11SRichard Henderson }
3263c482cb11SRichard Henderson 
3264c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
326514776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3266c482cb11SRichard Henderson {
3267c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3268c482cb11SRichard Henderson 
3269c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
3270df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3271c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
3272e28a8664SRichard Henderson         TCGMemOpIdx oi;
3273c482cb11SRichard Henderson 
3274c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
3275c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3276c482cb11SRichard Henderson 
3277e28a8664SRichard Henderson         oi = make_memop_idx(memop & ~MO_SIGN, idx);
327811d11d61SRichard Henderson         gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
3279df79b996SRichard Henderson #else
32801c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
328179b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
328279b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
328379b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
3284df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3285c482cb11SRichard Henderson     } else {
3286c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
3287c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3288c482cb11SRichard Henderson 
3289c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
3290c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
3291c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
3292c482cb11SRichard Henderson 
3293c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
3294c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3295c482cb11SRichard Henderson 
3296c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3297c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
3298c482cb11SRichard Henderson         }
3299c482cb11SRichard Henderson     }
3300c482cb11SRichard Henderson }
3301c482cb11SRichard Henderson 
3302c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
3303*4b473e0cSRichard Henderson static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = {          \
3304c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
3305c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
3306c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
3307c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
3308c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
3309df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
3310df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3311c482cb11SRichard Henderson };                                                                      \
3312c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
331314776ab5STony Nguyen     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop)    \
3314c482cb11SRichard Henderson {                                                                       \
3315b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3316c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3317c482cb11SRichard Henderson     } else {                                                            \
3318c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3319c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3320c482cb11SRichard Henderson     }                                                                   \
3321c482cb11SRichard Henderson }                                                                       \
3322c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
332314776ab5STony Nguyen     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop)    \
3324c482cb11SRichard Henderson {                                                                       \
3325b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3326c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3327c482cb11SRichard Henderson     } else {                                                            \
3328c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3329c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3330c482cb11SRichard Henderson     }                                                                   \
3331c482cb11SRichard Henderson }
3332c482cb11SRichard Henderson 
3333c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3334c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3335c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3336c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
33375507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smin, smin, 0)
33385507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umin, umin, 0)
33395507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smax, smax, 0)
33405507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umax, umax, 0)
3341c482cb11SRichard Henderson 
3342c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3343c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3344c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3345c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
33465507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smin_fetch, smin, 1)
33475507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umin_fetch, umin, 1)
33485507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smax_fetch, smax, 1)
33495507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umax_fetch, umax, 1)
3350c482cb11SRichard Henderson 
3351c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3352c482cb11SRichard Henderson {
3353c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3354c482cb11SRichard Henderson }
3355c482cb11SRichard Henderson 
3356c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3357c482cb11SRichard Henderson {
3358c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3359c482cb11SRichard Henderson }
3360c482cb11SRichard Henderson 
3361c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3362c482cb11SRichard Henderson 
3363c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3364