xref: /openbmc/qemu/tcg/tcg-op.c (revision 5507c2bf)
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"
2633c11879SPaolo Bonzini #include "qemu-common.h"
2733c11879SPaolo Bonzini #include "cpu.h"
2863c91552SPaolo Bonzini #include "exec/exec-all.h"
29951c6300SRichard Henderson #include "tcg.h"
30951c6300SRichard Henderson #include "tcg-op.h"
31b32dc337SPranith Kumar #include "tcg-mo.h"
32dcdaadb6SLluís Vilanova #include "trace-tcg.h"
33dcdaadb6SLluís Vilanova #include "trace/mem.h"
34951c6300SRichard Henderson 
353a13c3f3SRichard Henderson /* Reduce the number of ifdefs below.  This assumes that all uses of
363a13c3f3SRichard Henderson    TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
373a13c3f3SRichard Henderson    the compiler can eliminate.  */
383a13c3f3SRichard Henderson #if TCG_TARGET_REG_BITS == 64
393a13c3f3SRichard Henderson extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
403a13c3f3SRichard Henderson extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
413a13c3f3SRichard Henderson #define TCGV_LOW  TCGV_LOW_link_error
423a13c3f3SRichard Henderson #define TCGV_HIGH TCGV_HIGH_link_error
433a13c3f3SRichard Henderson #endif
44951c6300SRichard Henderson 
45b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
46951c6300SRichard Henderson {
47b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
4875e8b9b7SRichard Henderson     op->args[0] = a1;
49951c6300SRichard Henderson }
50951c6300SRichard Henderson 
51b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
52951c6300SRichard Henderson {
53b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
5475e8b9b7SRichard Henderson     op->args[0] = a1;
5575e8b9b7SRichard Henderson     op->args[1] = a2;
56951c6300SRichard Henderson }
57951c6300SRichard Henderson 
58b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
59951c6300SRichard Henderson {
60b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
6175e8b9b7SRichard Henderson     op->args[0] = a1;
6275e8b9b7SRichard Henderson     op->args[1] = a2;
6375e8b9b7SRichard Henderson     op->args[2] = a3;
64951c6300SRichard Henderson }
65951c6300SRichard Henderson 
66b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
67951c6300SRichard Henderson {
68b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
6975e8b9b7SRichard Henderson     op->args[0] = a1;
7075e8b9b7SRichard Henderson     op->args[1] = a2;
7175e8b9b7SRichard Henderson     op->args[2] = a3;
7275e8b9b7SRichard Henderson     op->args[3] = a4;
73951c6300SRichard Henderson }
74951c6300SRichard Henderson 
75b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
76b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5)
77951c6300SRichard Henderson {
78b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
7975e8b9b7SRichard Henderson     op->args[0] = a1;
8075e8b9b7SRichard Henderson     op->args[1] = a2;
8175e8b9b7SRichard Henderson     op->args[2] = a3;
8275e8b9b7SRichard Henderson     op->args[3] = a4;
8375e8b9b7SRichard Henderson     op->args[4] = a5;
84951c6300SRichard Henderson }
85951c6300SRichard Henderson 
86b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
87b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5, TCGArg a6)
88951c6300SRichard Henderson {
89b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
9075e8b9b7SRichard Henderson     op->args[0] = a1;
9175e8b9b7SRichard Henderson     op->args[1] = a2;
9275e8b9b7SRichard Henderson     op->args[2] = a3;
9375e8b9b7SRichard Henderson     op->args[3] = a4;
9475e8b9b7SRichard Henderson     op->args[4] = a5;
9575e8b9b7SRichard Henderson     op->args[5] = a6;
96951c6300SRichard Henderson }
97951c6300SRichard Henderson 
98f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
99f65e19bcSPranith Kumar {
100b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {
101b7e8b17aSRichard Henderson         tcg_gen_op1(INDEX_op_mb, mb_type);
102f65e19bcSPranith Kumar     }
103f65e19bcSPranith Kumar }
104f65e19bcSPranith Kumar 
105951c6300SRichard Henderson /* 32 bit ops */
106951c6300SRichard Henderson 
107951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
108951c6300SRichard Henderson {
109951c6300SRichard Henderson     /* some cases can be optimized here */
110951c6300SRichard Henderson     if (arg2 == 0) {
111951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
112951c6300SRichard Henderson     } else {
113951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
114951c6300SRichard Henderson         tcg_gen_add_i32(ret, arg1, t0);
115951c6300SRichard Henderson         tcg_temp_free_i32(t0);
116951c6300SRichard Henderson     }
117951c6300SRichard Henderson }
118951c6300SRichard Henderson 
119951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
120951c6300SRichard Henderson {
121951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
122951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
123951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
124951c6300SRichard Henderson     } else {
125951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg1);
126951c6300SRichard Henderson         tcg_gen_sub_i32(ret, t0, arg2);
127951c6300SRichard Henderson         tcg_temp_free_i32(t0);
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 {
137951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
138951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
139951c6300SRichard Henderson         tcg_temp_free_i32(t0);
140951c6300SRichard Henderson     }
141951c6300SRichard Henderson }
142951c6300SRichard Henderson 
143474b2e8fSRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
144951c6300SRichard Henderson {
145951c6300SRichard Henderson     TCGv_i32 t0;
146951c6300SRichard Henderson     /* Some cases can be optimized here.  */
147951c6300SRichard Henderson     switch (arg2) {
148951c6300SRichard Henderson     case 0:
149951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
150951c6300SRichard Henderson         return;
151474b2e8fSRichard Henderson     case -1:
152951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
153951c6300SRichard Henderson         return;
154474b2e8fSRichard Henderson     case 0xff:
155951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
156951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
157951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
158951c6300SRichard Henderson             return;
159951c6300SRichard Henderson         }
160951c6300SRichard Henderson         break;
161474b2e8fSRichard Henderson     case 0xffff:
162951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
163951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
164951c6300SRichard Henderson             return;
165951c6300SRichard Henderson         }
166951c6300SRichard Henderson         break;
167951c6300SRichard Henderson     }
168951c6300SRichard Henderson     t0 = tcg_const_i32(arg2);
169951c6300SRichard Henderson     tcg_gen_and_i32(ret, arg1, t0);
170951c6300SRichard Henderson     tcg_temp_free_i32(t0);
171951c6300SRichard Henderson }
172951c6300SRichard Henderson 
173951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
174951c6300SRichard Henderson {
175951c6300SRichard Henderson     /* Some cases can be optimized here.  */
176951c6300SRichard Henderson     if (arg2 == -1) {
177951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
178951c6300SRichard Henderson     } else if (arg2 == 0) {
179951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
180951c6300SRichard Henderson     } else {
181951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
182951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
183951c6300SRichard Henderson         tcg_temp_free_i32(t0);
184951c6300SRichard Henderson     }
185951c6300SRichard Henderson }
186951c6300SRichard Henderson 
187951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
188951c6300SRichard Henderson {
189951c6300SRichard Henderson     /* Some cases can be optimized here.  */
190951c6300SRichard Henderson     if (arg2 == 0) {
191951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
192951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
193951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
194951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
195951c6300SRichard Henderson     } else {
196951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
197951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, t0);
198951c6300SRichard Henderson         tcg_temp_free_i32(t0);
199951c6300SRichard Henderson     }
200951c6300SRichard Henderson }
201951c6300SRichard Henderson 
202474b2e8fSRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
203951c6300SRichard Henderson {
204474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
205951c6300SRichard Henderson     if (arg2 == 0) {
206951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
207951c6300SRichard Henderson     } else {
208951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
209951c6300SRichard Henderson         tcg_gen_shl_i32(ret, arg1, t0);
210951c6300SRichard Henderson         tcg_temp_free_i32(t0);
211951c6300SRichard Henderson     }
212951c6300SRichard Henderson }
213951c6300SRichard Henderson 
214474b2e8fSRichard Henderson void tcg_gen_shri_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 {
220951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
221951c6300SRichard Henderson         tcg_gen_shr_i32(ret, arg1, t0);
222951c6300SRichard Henderson         tcg_temp_free_i32(t0);
223951c6300SRichard Henderson     }
224951c6300SRichard Henderson }
225951c6300SRichard Henderson 
226474b2e8fSRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
227951c6300SRichard Henderson {
228474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
229951c6300SRichard Henderson     if (arg2 == 0) {
230951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
231951c6300SRichard Henderson     } else {
232951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
233951c6300SRichard Henderson         tcg_gen_sar_i32(ret, arg1, t0);
234951c6300SRichard Henderson         tcg_temp_free_i32(t0);
235951c6300SRichard Henderson     }
236951c6300SRichard Henderson }
237951c6300SRichard Henderson 
23842a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
239951c6300SRichard Henderson {
240951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
24142a268c2SRichard Henderson         tcg_gen_br(l);
242951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
24342a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
244951c6300SRichard Henderson     }
245951c6300SRichard Henderson }
246951c6300SRichard Henderson 
24742a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
248951c6300SRichard Henderson {
24937ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
25037ed3bf1SRichard Henderson         tcg_gen_br(l);
25137ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
252951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
25342a268c2SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, t0, l);
254951c6300SRichard Henderson         tcg_temp_free_i32(t0);
255951c6300SRichard Henderson     }
25637ed3bf1SRichard Henderson }
257951c6300SRichard Henderson 
258951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
259951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
260951c6300SRichard Henderson {
261951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
262951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
263951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
264951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
265951c6300SRichard Henderson     } else {
266951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
267951c6300SRichard Henderson     }
268951c6300SRichard Henderson }
269951c6300SRichard Henderson 
270951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
271951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
272951c6300SRichard Henderson {
273951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
274951c6300SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, t0);
275951c6300SRichard Henderson     tcg_temp_free_i32(t0);
276951c6300SRichard Henderson }
277951c6300SRichard Henderson 
278951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
279951c6300SRichard Henderson {
280b2e3ae94SRichard Henderson     if (arg2 == 0) {
281b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
282b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
283b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
284b2e3ae94SRichard Henderson     } else {
285951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
286951c6300SRichard Henderson         tcg_gen_mul_i32(ret, arg1, t0);
287951c6300SRichard Henderson         tcg_temp_free_i32(t0);
288951c6300SRichard Henderson     }
289b2e3ae94SRichard Henderson }
290951c6300SRichard Henderson 
291951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
292951c6300SRichard Henderson {
293951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
294951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
295951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
296951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
297951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
298951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
299951c6300SRichard Henderson         tcg_temp_free_i32(t0);
300951c6300SRichard Henderson     } else {
301951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
302951c6300SRichard Henderson     }
303951c6300SRichard Henderson }
304951c6300SRichard Henderson 
305951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
306951c6300SRichard Henderson {
307951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
308951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
309951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
310951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
311951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
312951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
313951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
314951c6300SRichard Henderson         tcg_temp_free_i32(t0);
315951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
316951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
317951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
318951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
319951c6300SRichard Henderson         tcg_temp_free_i32(t0);
320951c6300SRichard Henderson     } else {
321951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
322951c6300SRichard Henderson     }
323951c6300SRichard Henderson }
324951c6300SRichard Henderson 
325951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
326951c6300SRichard Henderson {
327951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
328951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
329951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
330951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
331951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
332951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
333951c6300SRichard Henderson         tcg_temp_free_i32(t0);
334951c6300SRichard Henderson     } else {
335951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
336951c6300SRichard Henderson     }
337951c6300SRichard Henderson }
338951c6300SRichard Henderson 
339951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
340951c6300SRichard Henderson {
341951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
342951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
343951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
344951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
345951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
346951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
347951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
348951c6300SRichard Henderson         tcg_temp_free_i32(t0);
349951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
350951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
351951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
352951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
353951c6300SRichard Henderson         tcg_temp_free_i32(t0);
354951c6300SRichard Henderson     } else {
355951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
356951c6300SRichard Henderson     }
357951c6300SRichard Henderson }
358951c6300SRichard Henderson 
359951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
360951c6300SRichard Henderson {
361951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
362951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
363951c6300SRichard Henderson     } else {
364951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
365951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
366951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
367951c6300SRichard Henderson         tcg_temp_free_i32(t0);
368951c6300SRichard Henderson     }
369951c6300SRichard Henderson }
370951c6300SRichard Henderson 
371951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
372951c6300SRichard Henderson {
373951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
374951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
375951c6300SRichard Henderson     } else {
376951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
377951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
378951c6300SRichard Henderson     }
379951c6300SRichard Henderson }
380951c6300SRichard Henderson 
381951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
382951c6300SRichard Henderson {
383951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
384951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
385951c6300SRichard Henderson     } else {
386951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
387951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
388951c6300SRichard Henderson     }
389951c6300SRichard Henderson }
390951c6300SRichard Henderson 
391951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
392951c6300SRichard Henderson {
393951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
394951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
395951c6300SRichard Henderson     } else {
396951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
397951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
398951c6300SRichard Henderson     }
399951c6300SRichard Henderson }
400951c6300SRichard Henderson 
401951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
402951c6300SRichard Henderson {
403951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
404951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
405951c6300SRichard Henderson     } else {
406951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
407951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
408951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
409951c6300SRichard Henderson         tcg_temp_free_i32(t0);
410951c6300SRichard Henderson     }
411951c6300SRichard Henderson }
412951c6300SRichard Henderson 
4130e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4140e28d006SRichard Henderson {
4150e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4160e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
4170e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
4180e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4190e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4200e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4210e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4220e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4230e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4240e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4250e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4260e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4270e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4280e28d006SRichard Henderson     } else {
4290e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4300e28d006SRichard Henderson     }
4310e28d006SRichard Henderson }
4320e28d006SRichard Henderson 
4330e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4340e28d006SRichard Henderson {
4350e28d006SRichard Henderson     TCGv_i32 t = tcg_const_i32(arg2);
4360e28d006SRichard Henderson     tcg_gen_clz_i32(ret, arg1, t);
4370e28d006SRichard Henderson     tcg_temp_free_i32(t);
4380e28d006SRichard Henderson }
4390e28d006SRichard Henderson 
4400e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4410e28d006SRichard Henderson {
4420e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4430e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4440e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4450e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4460e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4470e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4480e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4490e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4500e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4510e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4520e28d006SRichard Henderson         tcg_temp_free_i64(t2);
45314e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
45414e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
45514e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
45614e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
45714e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
45814e99210SRichard Henderson 
45914e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
46014e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
46114e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
46214e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
46314e99210SRichard Henderson         } else {
46414e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
46514e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
46614e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
46714e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
46814e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
46914e99210SRichard Henderson         }
47014e99210SRichard Henderson         z = tcg_const_i32(0);
47114e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
47214e99210SRichard Henderson         tcg_temp_free_i32(t);
47314e99210SRichard Henderson         tcg_temp_free_i32(z);
4740e28d006SRichard Henderson     } else {
4750e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4760e28d006SRichard Henderson     }
4770e28d006SRichard Henderson }
4780e28d006SRichard Henderson 
4790e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4800e28d006SRichard Henderson {
48114e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
48214e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
48314e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
48414e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
48514e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
48614e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
48714e99210SRichard Henderson         tcg_temp_free_i32(t);
48814e99210SRichard Henderson     } else {
4890e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32(arg2);
4900e28d006SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, t);
4910e28d006SRichard Henderson         tcg_temp_free_i32(t);
4920e28d006SRichard Henderson     }
49314e99210SRichard Henderson }
4940e28d006SRichard Henderson 
495086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
496086920c2SRichard Henderson {
497086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
498086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
499086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
500086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
501086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
502086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
503086920c2SRichard Henderson         tcg_temp_free_i32(t);
504086920c2SRichard Henderson     } else {
505086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
506086920c2SRichard Henderson     }
507086920c2SRichard Henderson }
508086920c2SRichard Henderson 
509a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
510a768e4e9SRichard Henderson {
511a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
512a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
513a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
514a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
515a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
516a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
517a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
518a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
519a768e4e9SRichard Henderson     } else {
520a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
521a768e4e9SRichard Henderson     }
522a768e4e9SRichard Henderson }
523a768e4e9SRichard Henderson 
524951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
525951c6300SRichard Henderson {
526951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
527951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
528951c6300SRichard Henderson     } else {
529951c6300SRichard Henderson         TCGv_i32 t0, t1;
530951c6300SRichard Henderson 
531951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
532951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
533951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
534951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
535951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
536951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
537951c6300SRichard Henderson         tcg_temp_free_i32(t0);
538951c6300SRichard Henderson         tcg_temp_free_i32(t1);
539951c6300SRichard Henderson     }
540951c6300SRichard Henderson }
541951c6300SRichard Henderson 
542951c6300SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
543951c6300SRichard Henderson {
544951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
545951c6300SRichard Henderson     /* some cases can be optimized here */
546951c6300SRichard Henderson     if (arg2 == 0) {
547951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
548951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
549951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
550951c6300SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, t0);
551951c6300SRichard Henderson         tcg_temp_free_i32(t0);
552951c6300SRichard Henderson     } else {
553951c6300SRichard Henderson         TCGv_i32 t0, t1;
554951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
555951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
556951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
557951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
558951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
559951c6300SRichard Henderson         tcg_temp_free_i32(t0);
560951c6300SRichard Henderson         tcg_temp_free_i32(t1);
561951c6300SRichard Henderson     }
562951c6300SRichard Henderson }
563951c6300SRichard Henderson 
564951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
565951c6300SRichard Henderson {
566951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
567951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
568951c6300SRichard Henderson     } else {
569951c6300SRichard Henderson         TCGv_i32 t0, t1;
570951c6300SRichard Henderson 
571951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
572951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
573951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
574951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
575951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
576951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
577951c6300SRichard Henderson         tcg_temp_free_i32(t0);
578951c6300SRichard Henderson         tcg_temp_free_i32(t1);
579951c6300SRichard Henderson     }
580951c6300SRichard Henderson }
581951c6300SRichard Henderson 
582951c6300SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
583951c6300SRichard Henderson {
584951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
585951c6300SRichard Henderson     /* some cases can be optimized here */
586951c6300SRichard Henderson     if (arg2 == 0) {
587951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
588951c6300SRichard Henderson     } else {
589951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
590951c6300SRichard Henderson     }
591951c6300SRichard Henderson }
592951c6300SRichard Henderson 
593951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
594951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
595951c6300SRichard Henderson {
596951c6300SRichard Henderson     uint32_t mask;
597951c6300SRichard Henderson     TCGv_i32 t1;
598951c6300SRichard Henderson 
599951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
6000d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
601951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
602951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
603951c6300SRichard Henderson 
6040d0d309dSRichard Henderson     if (len == 32) {
605951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
606951c6300SRichard Henderson         return;
607951c6300SRichard Henderson     }
608951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
609951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
610951c6300SRichard Henderson         return;
611951c6300SRichard Henderson     }
612951c6300SRichard Henderson 
613951c6300SRichard Henderson     mask = (1u << len) - 1;
614951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
615951c6300SRichard Henderson 
616951c6300SRichard Henderson     if (ofs + len < 32) {
617951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
618951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
619951c6300SRichard Henderson     } else {
620951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
621951c6300SRichard Henderson     }
622951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
623951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
624951c6300SRichard Henderson 
625951c6300SRichard Henderson     tcg_temp_free_i32(t1);
626951c6300SRichard Henderson }
627951c6300SRichard Henderson 
62807cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
62907cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
63007cc68d5SRichard Henderson {
63107cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
63207cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
63307cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
63407cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
63507cc68d5SRichard Henderson 
63607cc68d5SRichard Henderson     if (ofs + len == 32) {
63707cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
63807cc68d5SRichard Henderson     } else if (ofs == 0) {
63907cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
64007cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
64107cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
64207cc68d5SRichard Henderson         TCGv_i32 zero = tcg_const_i32(0);
64307cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
64407cc68d5SRichard Henderson         tcg_temp_free_i32(zero);
64507cc68d5SRichard Henderson     } else {
64607cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
64707cc68d5SRichard Henderson            which allows ARG to stay live.  */
64807cc68d5SRichard Henderson         switch (len) {
64907cc68d5SRichard Henderson         case 16:
65007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
65107cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
65207cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
65307cc68d5SRichard Henderson                 return;
65407cc68d5SRichard Henderson             }
65507cc68d5SRichard Henderson             break;
65607cc68d5SRichard Henderson         case 8:
65707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
65807cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
65907cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
66007cc68d5SRichard Henderson                 return;
66107cc68d5SRichard Henderson             }
66207cc68d5SRichard Henderson             break;
66307cc68d5SRichard Henderson         }
66407cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
66507cc68d5SRichard Henderson         switch (ofs + len) {
66607cc68d5SRichard Henderson         case 16:
66707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
66807cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
66907cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
67007cc68d5SRichard Henderson                 return;
67107cc68d5SRichard Henderson             }
67207cc68d5SRichard Henderson             break;
67307cc68d5SRichard Henderson         case 8:
67407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
67507cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
67607cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
67707cc68d5SRichard Henderson                 return;
67807cc68d5SRichard Henderson             }
67907cc68d5SRichard Henderson             break;
68007cc68d5SRichard Henderson         }
68107cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
68207cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
68307cc68d5SRichard Henderson     }
68407cc68d5SRichard Henderson }
68507cc68d5SRichard Henderson 
6867ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
6877ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
6887ec8bab3SRichard Henderson {
6897ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
6907ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
6917ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
6927ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
6937ec8bab3SRichard Henderson 
6947ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
6957ec8bab3SRichard Henderson     if (ofs + len == 32) {
6967ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
6977ec8bab3SRichard Henderson         return;
6987ec8bab3SRichard Henderson     }
6997ec8bab3SRichard Henderson     if (ofs == 0) {
7007ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
7017ec8bab3SRichard Henderson         return;
7027ec8bab3SRichard Henderson     }
7037ec8bab3SRichard Henderson 
7047ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
7057ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7067ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
7077ec8bab3SRichard Henderson         return;
7087ec8bab3SRichard Henderson     }
7097ec8bab3SRichard Henderson 
7107ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
7117ec8bab3SRichard Henderson     switch (ofs + len) {
7127ec8bab3SRichard Henderson     case 16:
7137ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7147ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7157ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7167ec8bab3SRichard Henderson             return;
7177ec8bab3SRichard Henderson         }
7187ec8bab3SRichard Henderson         break;
7197ec8bab3SRichard Henderson     case 8:
7207ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7217ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7227ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7237ec8bab3SRichard Henderson             return;
7247ec8bab3SRichard Henderson         }
7257ec8bab3SRichard Henderson         break;
7267ec8bab3SRichard Henderson     }
7277ec8bab3SRichard Henderson 
7287ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7297ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7307ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7317ec8bab3SRichard Henderson     switch (len) {
7327ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7337ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7347ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7357ec8bab3SRichard Henderson         break;
7367ec8bab3SRichard Henderson     default:
7377ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7387ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7397ec8bab3SRichard Henderson         break;
7407ec8bab3SRichard Henderson     }
7417ec8bab3SRichard Henderson }
7427ec8bab3SRichard Henderson 
7437ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7447ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7457ec8bab3SRichard Henderson {
7467ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7477ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7487ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7497ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7507ec8bab3SRichard Henderson 
7517ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7527ec8bab3SRichard Henderson     if (ofs + len == 32) {
7537ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7547ec8bab3SRichard Henderson         return;
7557ec8bab3SRichard Henderson     }
7567ec8bab3SRichard Henderson     if (ofs == 0) {
7577ec8bab3SRichard Henderson         switch (len) {
7587ec8bab3SRichard Henderson         case 16:
7597ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7607ec8bab3SRichard Henderson             return;
7617ec8bab3SRichard Henderson         case 8:
7627ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7637ec8bab3SRichard Henderson             return;
7647ec8bab3SRichard Henderson         }
7657ec8bab3SRichard Henderson     }
7667ec8bab3SRichard Henderson 
7677ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7687ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7697ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7707ec8bab3SRichard Henderson         return;
7717ec8bab3SRichard Henderson     }
7727ec8bab3SRichard Henderson 
7737ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7747ec8bab3SRichard Henderson     switch (ofs + len) {
7757ec8bab3SRichard Henderson     case 16:
7767ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7777ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7787ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7797ec8bab3SRichard Henderson             return;
7807ec8bab3SRichard Henderson         }
7817ec8bab3SRichard Henderson         break;
7827ec8bab3SRichard Henderson     case 8:
7837ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7847ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7857ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7867ec8bab3SRichard Henderson             return;
7877ec8bab3SRichard Henderson         }
7887ec8bab3SRichard Henderson         break;
7897ec8bab3SRichard Henderson     }
7907ec8bab3SRichard Henderson     switch (len) {
7917ec8bab3SRichard Henderson     case 16:
7927ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7937ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
7947ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
7957ec8bab3SRichard Henderson             return;
7967ec8bab3SRichard Henderson         }
7977ec8bab3SRichard Henderson         break;
7987ec8bab3SRichard Henderson     case 8:
7997ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8007ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8017ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
8027ec8bab3SRichard Henderson             return;
8037ec8bab3SRichard Henderson         }
8047ec8bab3SRichard Henderson         break;
8057ec8bab3SRichard Henderson     }
8067ec8bab3SRichard Henderson 
8077ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
8087ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
8097ec8bab3SRichard Henderson }
8107ec8bab3SRichard Henderson 
811951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
812951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
813951c6300SRichard Henderson {
81437ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
81537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
81637ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
81737ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
81837ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
819951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
820951c6300SRichard Henderson     } else {
821951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
822951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
823951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
824951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
825951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
826951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
827951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
828951c6300SRichard Henderson         tcg_temp_free_i32(t0);
829951c6300SRichard Henderson         tcg_temp_free_i32(t1);
830951c6300SRichard Henderson     }
831951c6300SRichard Henderson }
832951c6300SRichard Henderson 
833951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
834951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
835951c6300SRichard Henderson {
836951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
837951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
838951c6300SRichard Henderson     } else {
839951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
840951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
841951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
842951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
843951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
844951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
845951c6300SRichard Henderson         tcg_temp_free_i64(t0);
846951c6300SRichard Henderson         tcg_temp_free_i64(t1);
847951c6300SRichard Henderson     }
848951c6300SRichard Henderson }
849951c6300SRichard Henderson 
850951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
851951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
852951c6300SRichard Henderson {
853951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
854951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
855951c6300SRichard Henderson     } else {
856951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
857951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
858951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
859951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
860951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
861951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
862951c6300SRichard Henderson         tcg_temp_free_i64(t0);
863951c6300SRichard Henderson         tcg_temp_free_i64(t1);
864951c6300SRichard Henderson     }
865951c6300SRichard Henderson }
866951c6300SRichard Henderson 
867951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
868951c6300SRichard Henderson {
869951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
870951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
871951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
872951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
873951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
874951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
875951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
876951c6300SRichard Henderson         tcg_temp_free_i32(t);
877951c6300SRichard Henderson     } else {
878951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
879951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
880951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
881951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
882951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
883951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
884951c6300SRichard Henderson         tcg_temp_free_i64(t0);
885951c6300SRichard Henderson         tcg_temp_free_i64(t1);
886951c6300SRichard Henderson     }
887951c6300SRichard Henderson }
888951c6300SRichard Henderson 
889951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
890951c6300SRichard Henderson {
891951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
892951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
893951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
894951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
895951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
896951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
897951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
898951c6300SRichard Henderson         tcg_temp_free_i32(t);
899951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
900951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
901951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
902951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
903951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
904951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
905951c6300SRichard Henderson         /* Adjust for negative inputs.  */
906951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
907951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
908951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
909951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
910951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
911951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
912951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
913951c6300SRichard Henderson         tcg_temp_free_i32(t0);
914951c6300SRichard Henderson         tcg_temp_free_i32(t1);
915951c6300SRichard Henderson         tcg_temp_free_i32(t2);
916951c6300SRichard Henderson         tcg_temp_free_i32(t3);
917951c6300SRichard Henderson     } else {
918951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
919951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
920951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
921951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
922951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
923951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
924951c6300SRichard Henderson         tcg_temp_free_i64(t0);
925951c6300SRichard Henderson         tcg_temp_free_i64(t1);
926951c6300SRichard Henderson     }
927951c6300SRichard Henderson }
928951c6300SRichard Henderson 
9295087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9305087abfbSRichard Henderson {
9315087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9325087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9335087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9345087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9355087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9365087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9375087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9385087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9395087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9405087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9415087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9425087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9435087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9445087abfbSRichard Henderson     } else {
9455087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9465087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9475087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9485087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9495087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9505087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9515087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9525087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9535087abfbSRichard Henderson     }
9545087abfbSRichard Henderson }
9555087abfbSRichard Henderson 
956951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
957951c6300SRichard Henderson {
958951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
959951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
960951c6300SRichard Henderson     } else {
961951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
962951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
963951c6300SRichard Henderson     }
964951c6300SRichard Henderson }
965951c6300SRichard Henderson 
966951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
967951c6300SRichard Henderson {
968951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
969951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
970951c6300SRichard Henderson     } else {
971951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
972951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
973951c6300SRichard Henderson     }
974951c6300SRichard Henderson }
975951c6300SRichard Henderson 
976951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
977951c6300SRichard Henderson {
978951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
979951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
980951c6300SRichard Henderson     } else {
981951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
982951c6300SRichard Henderson     }
983951c6300SRichard Henderson }
984951c6300SRichard Henderson 
985951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
986951c6300SRichard Henderson {
987951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
988951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
989951c6300SRichard Henderson     } else {
990951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
991951c6300SRichard Henderson     }
992951c6300SRichard Henderson }
993951c6300SRichard Henderson 
994951c6300SRichard Henderson /* Note: we assume the two high bytes are set to zero */
995951c6300SRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
996951c6300SRichard Henderson {
997951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
998951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
999951c6300SRichard Henderson     } else {
1000951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1001951c6300SRichard Henderson 
1002951c6300SRichard Henderson         tcg_gen_ext8u_i32(t0, arg);
1003951c6300SRichard Henderson         tcg_gen_shli_i32(t0, t0, 8);
1004951c6300SRichard Henderson         tcg_gen_shri_i32(ret, arg, 8);
1005951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t0);
1006951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1007951c6300SRichard Henderson     }
1008951c6300SRichard Henderson }
1009951c6300SRichard Henderson 
1010951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1011951c6300SRichard Henderson {
1012951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1013951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
1014951c6300SRichard Henderson     } else {
1015951c6300SRichard Henderson         TCGv_i32 t0, t1;
1016951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1017951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1018951c6300SRichard Henderson 
1019951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg, 24);
1020951c6300SRichard Henderson 
1021951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg, 0x0000ff00);
1022951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);
1023951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
1024951c6300SRichard Henderson 
1025951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 8);
1026951c6300SRichard Henderson         tcg_gen_andi_i32(t1, t1, 0x0000ff00);
1027951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
1028951c6300SRichard Henderson 
1029951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 24);
1030951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1031951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1032951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1033951c6300SRichard Henderson     }
1034951c6300SRichard Henderson }
1035951c6300SRichard Henderson 
1036b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1037b87fb8cdSRichard Henderson {
1038b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1039b87fb8cdSRichard Henderson }
1040b87fb8cdSRichard Henderson 
1041b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1042b87fb8cdSRichard Henderson {
1043b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1044b87fb8cdSRichard Henderson }
1045b87fb8cdSRichard Henderson 
1046b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1047b87fb8cdSRichard Henderson {
1048b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1049b87fb8cdSRichard Henderson }
1050b87fb8cdSRichard Henderson 
1051b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1052b87fb8cdSRichard Henderson {
1053b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1054b87fb8cdSRichard Henderson }
1055b87fb8cdSRichard Henderson 
1056951c6300SRichard Henderson /* 64-bit ops */
1057951c6300SRichard Henderson 
1058951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1059951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1060951c6300SRichard Henderson 
1061951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1062951c6300SRichard Henderson {
1063951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1064951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1065951c6300SRichard Henderson }
1066951c6300SRichard Henderson 
1067951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1068951c6300SRichard Henderson {
1069951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1070951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1071951c6300SRichard Henderson }
1072951c6300SRichard Henderson 
1073951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1074951c6300SRichard Henderson {
1075951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1076951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1077951c6300SRichard Henderson }
1078951c6300SRichard Henderson 
1079951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1080951c6300SRichard Henderson {
1081951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1082951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1083951c6300SRichard Henderson }
1084951c6300SRichard Henderson 
1085951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1086951c6300SRichard Henderson {
1087951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
10883ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1089951c6300SRichard Henderson }
1090951c6300SRichard Henderson 
1091951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1092951c6300SRichard Henderson {
1093951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1094951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1095951c6300SRichard Henderson }
1096951c6300SRichard Henderson 
1097951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1098951c6300SRichard Henderson {
1099951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1100951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1101951c6300SRichard Henderson }
1102951c6300SRichard Henderson 
1103951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1104951c6300SRichard Henderson {
1105951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1106951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1107951c6300SRichard Henderson }
1108951c6300SRichard Henderson 
1109951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1110951c6300SRichard Henderson {
1111951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1112951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1113951c6300SRichard Henderson }
1114951c6300SRichard Henderson 
1115951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1116951c6300SRichard Henderson {
1117951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1118951c6300SRichard Henderson        they cannot be the same temporary */
1119cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1120951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1121951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1122951c6300SRichard Henderson #else
1123951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1124951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1125951c6300SRichard Henderson #endif
1126951c6300SRichard Henderson }
1127951c6300SRichard Henderson 
1128951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1129951c6300SRichard Henderson {
1130cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1131951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1132951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1133951c6300SRichard Henderson #else
1134951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1135951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1136951c6300SRichard Henderson #endif
1137951c6300SRichard Henderson }
1138951c6300SRichard Henderson 
1139951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1140951c6300SRichard Henderson {
1141951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1142951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1143951c6300SRichard Henderson }
1144951c6300SRichard Henderson 
1145951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1146951c6300SRichard Henderson {
1147951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1148951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1149951c6300SRichard Henderson }
1150951c6300SRichard Henderson 
1151951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1152951c6300SRichard Henderson {
1153951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1154951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1155951c6300SRichard Henderson }
1156951c6300SRichard Henderson 
1157951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1158951c6300SRichard Henderson {
1159951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1160951c6300SRichard Henderson }
1161951c6300SRichard Henderson 
1162951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1163951c6300SRichard Henderson {
1164951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1165951c6300SRichard Henderson }
1166951c6300SRichard Henderson 
1167951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1168951c6300SRichard Henderson {
1169951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1170951c6300SRichard Henderson }
1171951c6300SRichard Henderson 
1172951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1173951c6300SRichard Henderson {
1174951c6300SRichard Henderson     TCGv_i64 t0;
1175951c6300SRichard Henderson     TCGv_i32 t1;
1176951c6300SRichard Henderson 
1177951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1178951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1179951c6300SRichard Henderson 
1180951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1181951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1182951c6300SRichard Henderson 
1183951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1184951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1185951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1186951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1187951c6300SRichard Henderson 
1188951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1189951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1190951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1191951c6300SRichard Henderson }
1192951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1193951c6300SRichard Henderson 
1194951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1195951c6300SRichard Henderson {
1196951c6300SRichard Henderson     /* some cases can be optimized here */
1197951c6300SRichard Henderson     if (arg2 == 0) {
1198951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1199951c6300SRichard Henderson     } else {
1200951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1201951c6300SRichard Henderson         tcg_gen_add_i64(ret, arg1, t0);
1202951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1203951c6300SRichard Henderson     }
1204951c6300SRichard Henderson }
1205951c6300SRichard Henderson 
1206951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1207951c6300SRichard Henderson {
1208951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1209951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1210951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
1211951c6300SRichard Henderson     } else {
1212951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg1);
1213951c6300SRichard Henderson         tcg_gen_sub_i64(ret, t0, arg2);
1214951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1215951c6300SRichard Henderson     }
1216951c6300SRichard Henderson }
1217951c6300SRichard Henderson 
1218951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1219951c6300SRichard Henderson {
1220951c6300SRichard Henderson     /* some cases can be optimized here */
1221951c6300SRichard Henderson     if (arg2 == 0) {
1222951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1223951c6300SRichard Henderson     } else {
1224951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1225951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1226951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1227951c6300SRichard Henderson     }
1228951c6300SRichard Henderson }
1229951c6300SRichard Henderson 
1230474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1231951c6300SRichard Henderson {
12323a13c3f3SRichard Henderson     TCGv_i64 t0;
12333a13c3f3SRichard Henderson 
12343a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1235951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1236951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12373a13c3f3SRichard Henderson         return;
12383a13c3f3SRichard Henderson     }
12393a13c3f3SRichard Henderson 
1240951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1241951c6300SRichard Henderson     switch (arg2) {
1242951c6300SRichard Henderson     case 0:
1243951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1244951c6300SRichard Henderson         return;
1245474b2e8fSRichard Henderson     case -1:
1246951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1247951c6300SRichard Henderson         return;
1248474b2e8fSRichard Henderson     case 0xff:
1249951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1250951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1251951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1252951c6300SRichard Henderson             return;
1253951c6300SRichard Henderson         }
1254951c6300SRichard Henderson         break;
1255474b2e8fSRichard Henderson     case 0xffff:
1256951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1257951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1258951c6300SRichard Henderson             return;
1259951c6300SRichard Henderson         }
1260951c6300SRichard Henderson         break;
1261474b2e8fSRichard Henderson     case 0xffffffffu:
1262951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1263951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1264951c6300SRichard Henderson             return;
1265951c6300SRichard Henderson         }
1266951c6300SRichard Henderson         break;
1267951c6300SRichard Henderson     }
1268951c6300SRichard Henderson     t0 = tcg_const_i64(arg2);
1269951c6300SRichard Henderson     tcg_gen_and_i64(ret, arg1, t0);
1270951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1271951c6300SRichard Henderson }
1272951c6300SRichard Henderson 
1273951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1274951c6300SRichard Henderson {
12753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1276951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1277951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12783a13c3f3SRichard Henderson         return;
12793a13c3f3SRichard Henderson     }
1280951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1281951c6300SRichard Henderson     if (arg2 == -1) {
1282951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1283951c6300SRichard Henderson     } else if (arg2 == 0) {
1284951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1285951c6300SRichard Henderson     } else {
1286951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1287951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1288951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1289951c6300SRichard Henderson     }
1290951c6300SRichard Henderson }
1291951c6300SRichard Henderson 
1292951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1293951c6300SRichard Henderson {
12943a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1295951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1296951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12973a13c3f3SRichard Henderson         return;
12983a13c3f3SRichard Henderson     }
1299951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1300951c6300SRichard Henderson     if (arg2 == 0) {
1301951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1302951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1303951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1304951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1305951c6300SRichard Henderson     } else {
1306951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1307951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, t0);
1308951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1309951c6300SRichard Henderson     }
1310951c6300SRichard Henderson }
1311951c6300SRichard Henderson 
1312951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1313951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1314951c6300SRichard Henderson {
1315951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1316951c6300SRichard Henderson     if (c == 0) {
1317951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1318951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1319951c6300SRichard Henderson     } else if (c >= 32) {
1320951c6300SRichard Henderson         c -= 32;
1321951c6300SRichard Henderson         if (right) {
1322951c6300SRichard Henderson             if (arith) {
1323951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1324951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1325951c6300SRichard Henderson             } else {
1326951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1327951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1328951c6300SRichard Henderson             }
1329951c6300SRichard Henderson         } else {
1330951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1331951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1332951c6300SRichard Henderson         }
1333951c6300SRichard Henderson     } else {
1334951c6300SRichard Henderson         TCGv_i32 t0, t1;
1335951c6300SRichard Henderson 
1336951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1337951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1338951c6300SRichard Henderson         if (right) {
1339951c6300SRichard Henderson             tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
1340951c6300SRichard Henderson             if (arith) {
1341951c6300SRichard Henderson                 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
1342951c6300SRichard Henderson             } else {
1343951c6300SRichard Henderson                 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
1344951c6300SRichard Henderson             }
1345951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1346951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
1347951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
1348951c6300SRichard Henderson         } else {
1349951c6300SRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
1350951c6300SRichard Henderson             /* Note: ret can be the same as arg1, so we use t1 */
1351951c6300SRichard Henderson             tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
1352951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1353951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
1354951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1355951c6300SRichard Henderson         }
1356951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1357951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1358951c6300SRichard Henderson     }
1359951c6300SRichard Henderson }
1360951c6300SRichard Henderson 
1361474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1362951c6300SRichard Henderson {
1363474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
13643a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13653a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
13663a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1367951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1368951c6300SRichard Henderson     } else {
1369951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1370951c6300SRichard Henderson         tcg_gen_shl_i64(ret, arg1, t0);
1371951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1372951c6300SRichard Henderson     }
1373951c6300SRichard Henderson }
1374951c6300SRichard Henderson 
1375474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1376951c6300SRichard Henderson {
1377474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
13783a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13793a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
13803a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1381951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1382951c6300SRichard Henderson     } else {
1383951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1384951c6300SRichard Henderson         tcg_gen_shr_i64(ret, arg1, t0);
1385951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1386951c6300SRichard Henderson     }
1387951c6300SRichard Henderson }
1388951c6300SRichard Henderson 
1389474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1390951c6300SRichard Henderson {
1391474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
13923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13933a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
13943a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1395951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1396951c6300SRichard Henderson     } else {
1397951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1398951c6300SRichard Henderson         tcg_gen_sar_i64(ret, arg1, t0);
1399951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1400951c6300SRichard Henderson     }
1401951c6300SRichard Henderson }
1402951c6300SRichard Henderson 
140342a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1404951c6300SRichard Henderson {
1405951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
140642a268c2SRichard Henderson         tcg_gen_br(l);
1407951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
14083a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1409951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1410951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
141142a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14123a13c3f3SRichard Henderson         } else {
141342a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
141442a268c2SRichard Henderson                               label_arg(l));
14153a13c3f3SRichard Henderson         }
1416951c6300SRichard Henderson     }
1417951c6300SRichard Henderson }
1418951c6300SRichard Henderson 
141942a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1420951c6300SRichard Henderson {
1421951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
142242a268c2SRichard Henderson         tcg_gen_br(l);
1423951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1424951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
142542a268c2SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, t0, l);
1426951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1427951c6300SRichard Henderson     }
1428951c6300SRichard Henderson }
1429951c6300SRichard Henderson 
1430951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1431951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1432951c6300SRichard Henderson {
1433951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1434951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1435951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1436951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1437951c6300SRichard Henderson     } else {
14383a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1439951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1440951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1441951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1442951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
14433a13c3f3SRichard Henderson         } else {
1444951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
14453a13c3f3SRichard Henderson         }
1446951c6300SRichard Henderson     }
1447951c6300SRichard Henderson }
1448951c6300SRichard Henderson 
1449951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1450951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1451951c6300SRichard Henderson {
1452951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1453951c6300SRichard Henderson     tcg_gen_setcond_i64(cond, ret, arg1, t0);
1454951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1455951c6300SRichard Henderson }
1456951c6300SRichard Henderson 
1457951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1458951c6300SRichard Henderson {
1459b2e3ae94SRichard Henderson     if (arg2 == 0) {
1460b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1461b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1462b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1463b2e3ae94SRichard Henderson     } else {
1464951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1465951c6300SRichard Henderson         tcg_gen_mul_i64(ret, arg1, t0);
1466951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1467951c6300SRichard Henderson     }
1468b2e3ae94SRichard Henderson }
1469951c6300SRichard Henderson 
1470951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1471951c6300SRichard Henderson {
1472951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1473951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1474951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1475951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1476951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1477951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1478951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1479951c6300SRichard Henderson     } else {
1480951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1481951c6300SRichard Henderson     }
1482951c6300SRichard Henderson }
1483951c6300SRichard Henderson 
1484951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1485951c6300SRichard Henderson {
1486951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1487951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1488951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1489951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1490951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1491951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1492951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1493951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1494951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1495951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1496951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1497951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1498951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1499951c6300SRichard Henderson     } else {
1500951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1501951c6300SRichard Henderson     }
1502951c6300SRichard Henderson }
1503951c6300SRichard Henderson 
1504951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1505951c6300SRichard Henderson {
1506951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1507951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1508951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1509951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1510951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1511951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1512951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1513951c6300SRichard Henderson     } else {
1514951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1515951c6300SRichard Henderson     }
1516951c6300SRichard Henderson }
1517951c6300SRichard Henderson 
1518951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1519951c6300SRichard Henderson {
1520951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1521951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1522951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1523951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1524951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1525951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1526951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1527951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1528951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1529951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1530951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1531951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1532951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1533951c6300SRichard Henderson     } else {
1534951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1535951c6300SRichard Henderson     }
1536951c6300SRichard Henderson }
1537951c6300SRichard Henderson 
1538951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1539951c6300SRichard Henderson {
15403a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1541951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1542951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15433a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1544951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1545951c6300SRichard Henderson     } else {
1546951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1547951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1548951c6300SRichard Henderson     }
1549951c6300SRichard Henderson }
1550951c6300SRichard Henderson 
1551951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1552951c6300SRichard Henderson {
15533a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1554951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1555951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15563a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1557951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1558951c6300SRichard Henderson     } else {
1559951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1560951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1561951c6300SRichard Henderson     }
1562951c6300SRichard Henderson }
1563951c6300SRichard Henderson 
1564951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1565951c6300SRichard Henderson {
15663a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1567951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1568951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15693a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1570951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1571951c6300SRichard Henderson     } else {
1572951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1573951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1574951c6300SRichard Henderson     }
1575951c6300SRichard Henderson }
1576951c6300SRichard Henderson 
1577951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1578951c6300SRichard Henderson {
15793a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1580951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1581951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15823a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1583951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1584951c6300SRichard Henderson     } else {
1585951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1586951c6300SRichard Henderson     }
1587951c6300SRichard Henderson }
1588951c6300SRichard Henderson 
1589951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1590951c6300SRichard Henderson {
15913a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1592951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1593951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15943a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1595951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1596951c6300SRichard Henderson     } else {
1597951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1598951c6300SRichard Henderson     }
1599951c6300SRichard Henderson }
1600951c6300SRichard Henderson 
1601951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1602951c6300SRichard Henderson {
16033a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1604951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1605951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16063a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1607951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1608951c6300SRichard Henderson     } else {
1609951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1610951c6300SRichard Henderson     }
1611951c6300SRichard Henderson }
1612951c6300SRichard Henderson 
1613951c6300SRichard Henderson /* Note: we assume the six high bytes are set to zero */
1614951c6300SRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
1615951c6300SRichard Henderson {
16163a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1617951c6300SRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1618951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16193a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
1620951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
1621951c6300SRichard Henderson     } else {
1622951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1623951c6300SRichard Henderson 
1624951c6300SRichard Henderson         tcg_gen_ext8u_i64(t0, arg);
1625951c6300SRichard Henderson         tcg_gen_shli_i64(t0, t0, 8);
1626951c6300SRichard Henderson         tcg_gen_shri_i64(ret, arg, 8);
1627951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t0);
1628951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1629951c6300SRichard Henderson     }
1630951c6300SRichard Henderson }
1631951c6300SRichard Henderson 
1632951c6300SRichard Henderson /* Note: we assume the four high bytes are set to zero */
1633951c6300SRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
1634951c6300SRichard Henderson {
16353a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1636951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1637951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16383a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
1639951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
1640951c6300SRichard Henderson     } else {
1641951c6300SRichard Henderson         TCGv_i64 t0, t1;
1642951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1643951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1644951c6300SRichard Henderson 
1645951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 24);
1646951c6300SRichard Henderson         tcg_gen_ext32u_i64(t0, t0);
1647951c6300SRichard Henderson 
1648951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1649951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1650951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1651951c6300SRichard Henderson 
1652951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1653951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1654951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1655951c6300SRichard Henderson 
1656951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1657951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1658951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1659951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1660951c6300SRichard Henderson     }
1661951c6300SRichard Henderson }
1662951c6300SRichard Henderson 
1663951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1664951c6300SRichard Henderson {
16653a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1666951c6300SRichard Henderson         TCGv_i32 t0, t1;
1667951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1668951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1669951c6300SRichard Henderson 
1670951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1671951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1672951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1673951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1674951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1675951c6300SRichard Henderson         tcg_temp_free_i32(t1);
16763a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1677951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
1678951c6300SRichard Henderson     } else {
1679951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1680951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1681951c6300SRichard Henderson 
1682951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 56);
1683951c6300SRichard Henderson 
1684951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1685951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 40);
1686951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1687951c6300SRichard Henderson 
1688951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x00ff0000);
1689951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 24);
1690951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1691951c6300SRichard Henderson 
1692951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0xff000000);
1693951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1694951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1695951c6300SRichard Henderson 
1696951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1697951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0xff000000);
1698951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1699951c6300SRichard Henderson 
1700951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1701951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x00ff0000);
1702951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1703951c6300SRichard Henderson 
1704951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 40);
1705951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1706951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1707951c6300SRichard Henderson 
1708951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 56);
1709951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1710951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1711951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1712951c6300SRichard Henderson     }
1713951c6300SRichard Henderson }
1714951c6300SRichard Henderson 
1715951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1716951c6300SRichard Henderson {
17173a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17183a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17193a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
17203a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1721951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1722951c6300SRichard Henderson     } else {
1723951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1724951c6300SRichard Henderson     }
1725951c6300SRichard Henderson }
1726951c6300SRichard Henderson 
1727951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1728951c6300SRichard Henderson {
17293a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17303a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17313a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17323a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1733951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1734951c6300SRichard Henderson     } else {
1735951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1736951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1737951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1738951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1739951c6300SRichard Henderson     }
1740951c6300SRichard Henderson }
1741951c6300SRichard Henderson 
1742951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1743951c6300SRichard Henderson {
17443a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17453a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17463a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17473a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1748951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1749951c6300SRichard Henderson     } else {
1750951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1751951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1752951c6300SRichard Henderson     }
1753951c6300SRichard Henderson }
1754951c6300SRichard Henderson 
1755951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1756951c6300SRichard Henderson {
17573a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17583a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17593a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17603a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1761951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1762951c6300SRichard Henderson     } else {
1763951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1764951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1765951c6300SRichard Henderson     }
1766951c6300SRichard Henderson }
1767951c6300SRichard Henderson 
1768951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1769951c6300SRichard Henderson {
17703a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17713a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17723a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17733a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1774951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1775951c6300SRichard Henderson     } else {
1776951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1777951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1778951c6300SRichard Henderson     }
1779951c6300SRichard Henderson }
1780951c6300SRichard Henderson 
1781951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1782951c6300SRichard Henderson {
17833a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17843a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17853a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17863a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1787951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1788951c6300SRichard Henderson     } else {
1789951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1790951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1791951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1792951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1793951c6300SRichard Henderson     }
1794951c6300SRichard Henderson }
1795951c6300SRichard Henderson 
17960e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
17970e28d006SRichard Henderson {
17980e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
17990e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
18000e28d006SRichard Henderson     } else {
18010e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
18020e28d006SRichard Henderson     }
18030e28d006SRichard Henderson }
18040e28d006SRichard Henderson 
18050e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18060e28d006SRichard Henderson {
18070e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18080e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
18090e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18100e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32((uint32_t)arg2 - 32);
18110e28d006SRichard Henderson         tcg_gen_clz_i32(t, TCGV_LOW(arg1), t);
18120e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
18130e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
18140e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18150e28d006SRichard Henderson         tcg_temp_free_i32(t);
18160e28d006SRichard Henderson     } else {
18170e28d006SRichard Henderson         TCGv_i64 t = tcg_const_i64(arg2);
18180e28d006SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t);
18190e28d006SRichard Henderson         tcg_temp_free_i64(t);
18200e28d006SRichard Henderson     }
18210e28d006SRichard Henderson }
18220e28d006SRichard Henderson 
18230e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18240e28d006SRichard Henderson {
18250e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
18260e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
182714e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
182814e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
182914e99210SRichard Henderson 
183014e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
183114e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
183214e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
183314e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
183414e99210SRichard Henderson         } else {
183514e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
183614e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
183714e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
183814e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
183914e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
184014e99210SRichard Henderson         }
184114e99210SRichard Henderson         z = tcg_const_i64(0);
184214e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
184314e99210SRichard Henderson         tcg_temp_free_i64(t);
184414e99210SRichard Henderson         tcg_temp_free_i64(z);
18450e28d006SRichard Henderson     } else {
18460e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
18470e28d006SRichard Henderson     }
18480e28d006SRichard Henderson }
18490e28d006SRichard Henderson 
18500e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18510e28d006SRichard Henderson {
18520e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18530e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
18540e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18550e28d006SRichard Henderson         TCGv_i32 t32 = tcg_const_i32((uint32_t)arg2 - 32);
18560e28d006SRichard Henderson         tcg_gen_ctz_i32(t32, TCGV_HIGH(arg1), t32);
18570e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
18580e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
18590e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18600e28d006SRichard Henderson         tcg_temp_free_i32(t32);
186114e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
186214e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
186314e99210SRichard Henderson                && arg2 == 64) {
186414e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
186514e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
186614e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
186714e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
186814e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
186914e99210SRichard Henderson         tcg_temp_free_i64(t);
18700e28d006SRichard Henderson     } else {
18710e28d006SRichard Henderson         TCGv_i64 t64 = tcg_const_i64(arg2);
18720e28d006SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t64);
18730e28d006SRichard Henderson         tcg_temp_free_i64(t64);
18740e28d006SRichard Henderson     }
18750e28d006SRichard Henderson }
18760e28d006SRichard Henderson 
1877086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
1878086920c2SRichard Henderson {
1879086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
1880086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1881086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
1882086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
1883086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
1884086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
1885086920c2SRichard Henderson         tcg_temp_free_i64(t);
1886086920c2SRichard Henderson     } else {
1887086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
1888086920c2SRichard Henderson     }
1889086920c2SRichard Henderson }
1890086920c2SRichard Henderson 
1891a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
1892a768e4e9SRichard Henderson {
1893a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
1894a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
1895a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
1896a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1897a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1898a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
1899a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1900a768e4e9SRichard Henderson     } else {
1901a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
1902a768e4e9SRichard Henderson     }
1903a768e4e9SRichard Henderson }
1904a768e4e9SRichard Henderson 
1905951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1906951c6300SRichard Henderson {
1907951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1908951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1909951c6300SRichard Henderson     } else {
1910951c6300SRichard Henderson         TCGv_i64 t0, t1;
1911951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1912951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1913951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1914951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1915951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1916951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1917951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1918951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1919951c6300SRichard Henderson     }
1920951c6300SRichard Henderson }
1921951c6300SRichard Henderson 
1922951c6300SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1923951c6300SRichard Henderson {
1924951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1925951c6300SRichard Henderson     /* some cases can be optimized here */
1926951c6300SRichard Henderson     if (arg2 == 0) {
1927951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1928951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
1929951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1930951c6300SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, t0);
1931951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1932951c6300SRichard Henderson     } else {
1933951c6300SRichard Henderson         TCGv_i64 t0, t1;
1934951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1935951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1936951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
1937951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
1938951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1939951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1940951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1941951c6300SRichard Henderson     }
1942951c6300SRichard Henderson }
1943951c6300SRichard Henderson 
1944951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1945951c6300SRichard Henderson {
1946951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1947951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
1948951c6300SRichard Henderson     } else {
1949951c6300SRichard Henderson         TCGv_i64 t0, t1;
1950951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1951951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1952951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
1953951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1954951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
1955951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1956951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1957951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1958951c6300SRichard Henderson     }
1959951c6300SRichard Henderson }
1960951c6300SRichard Henderson 
1961951c6300SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1962951c6300SRichard Henderson {
1963951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1964951c6300SRichard Henderson     /* some cases can be optimized here */
1965951c6300SRichard Henderson     if (arg2 == 0) {
1966951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1967951c6300SRichard Henderson     } else {
1968951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
1969951c6300SRichard Henderson     }
1970951c6300SRichard Henderson }
1971951c6300SRichard Henderson 
1972951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
1973951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
1974951c6300SRichard Henderson {
1975951c6300SRichard Henderson     uint64_t mask;
1976951c6300SRichard Henderson     TCGv_i64 t1;
1977951c6300SRichard Henderson 
1978951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
19790d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
1980951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
1981951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
1982951c6300SRichard Henderson 
19830d0d309dSRichard Henderson     if (len == 64) {
1984951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
1985951c6300SRichard Henderson         return;
1986951c6300SRichard Henderson     }
1987951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
1988951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
1989951c6300SRichard Henderson         return;
1990951c6300SRichard Henderson     }
1991951c6300SRichard Henderson 
19923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1993951c6300SRichard Henderson         if (ofs >= 32) {
1994951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
1995951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
1996951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1997951c6300SRichard Henderson             return;
1998951c6300SRichard Henderson         }
1999951c6300SRichard Henderson         if (ofs + len <= 32) {
2000951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2001951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2002951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2003951c6300SRichard Henderson             return;
2004951c6300SRichard Henderson         }
20053a13c3f3SRichard Henderson     }
2006951c6300SRichard Henderson 
2007951c6300SRichard Henderson     mask = (1ull << len) - 1;
2008951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2009951c6300SRichard Henderson 
2010951c6300SRichard Henderson     if (ofs + len < 64) {
2011951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2012951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2013951c6300SRichard Henderson     } else {
2014951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2015951c6300SRichard Henderson     }
2016951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2017951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2018951c6300SRichard Henderson 
2019951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2020951c6300SRichard Henderson }
2021951c6300SRichard Henderson 
202207cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
202307cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
202407cc68d5SRichard Henderson {
202507cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
202607cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
202707cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
202807cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
202907cc68d5SRichard Henderson 
203007cc68d5SRichard Henderson     if (ofs + len == 64) {
203107cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
203207cc68d5SRichard Henderson     } else if (ofs == 0) {
203307cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
203407cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
203507cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
203607cc68d5SRichard Henderson         TCGv_i64 zero = tcg_const_i64(0);
203707cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
203807cc68d5SRichard Henderson         tcg_temp_free_i64(zero);
203907cc68d5SRichard Henderson     } else {
204007cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
204107cc68d5SRichard Henderson             if (ofs >= 32) {
204207cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
204307cc68d5SRichard Henderson                                       ofs - 32, len);
204407cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
204507cc68d5SRichard Henderson                 return;
204607cc68d5SRichard Henderson             }
204707cc68d5SRichard Henderson             if (ofs + len <= 32) {
204807cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
204907cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
205007cc68d5SRichard Henderson                 return;
205107cc68d5SRichard Henderson             }
205207cc68d5SRichard Henderson         }
205307cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
205407cc68d5SRichard Henderson            which allows ARG to stay live.  */
205507cc68d5SRichard Henderson         switch (len) {
205607cc68d5SRichard Henderson         case 32:
205707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
205807cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
205907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
206007cc68d5SRichard Henderson                 return;
206107cc68d5SRichard Henderson             }
206207cc68d5SRichard Henderson             break;
206307cc68d5SRichard Henderson         case 16:
206407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
206507cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
206607cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
206707cc68d5SRichard Henderson                 return;
206807cc68d5SRichard Henderson             }
206907cc68d5SRichard Henderson             break;
207007cc68d5SRichard Henderson         case 8:
207107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
207207cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
207307cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
207407cc68d5SRichard Henderson                 return;
207507cc68d5SRichard Henderson             }
207607cc68d5SRichard Henderson             break;
207707cc68d5SRichard Henderson         }
207807cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
207907cc68d5SRichard Henderson         switch (ofs + len) {
208007cc68d5SRichard Henderson         case 32:
208107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
208207cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
208307cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
208407cc68d5SRichard Henderson                 return;
208507cc68d5SRichard Henderson             }
208607cc68d5SRichard Henderson             break;
208707cc68d5SRichard Henderson         case 16:
208807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
208907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
209007cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
209107cc68d5SRichard Henderson                 return;
209207cc68d5SRichard Henderson             }
209307cc68d5SRichard Henderson             break;
209407cc68d5SRichard Henderson         case 8:
209507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
209607cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
209707cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
209807cc68d5SRichard Henderson                 return;
209907cc68d5SRichard Henderson             }
210007cc68d5SRichard Henderson             break;
210107cc68d5SRichard Henderson         }
210207cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
210307cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
210407cc68d5SRichard Henderson     }
210507cc68d5SRichard Henderson }
210607cc68d5SRichard Henderson 
21077ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
21087ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
21097ec8bab3SRichard Henderson {
21107ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
21117ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
21127ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
21137ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
21147ec8bab3SRichard Henderson 
21157ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
21167ec8bab3SRichard Henderson     if (ofs + len == 64) {
21177ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
21187ec8bab3SRichard Henderson         return;
21197ec8bab3SRichard Henderson     }
21207ec8bab3SRichard Henderson     if (ofs == 0) {
21217ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
21227ec8bab3SRichard Henderson         return;
21237ec8bab3SRichard Henderson     }
21247ec8bab3SRichard Henderson 
21257ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
21267ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
21277ec8bab3SRichard Henderson         if (ofs >= 32) {
21287ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
21297ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21307ec8bab3SRichard Henderson             return;
21317ec8bab3SRichard Henderson         }
21327ec8bab3SRichard Henderson         if (ofs + len <= 32) {
21337ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
21347ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21357ec8bab3SRichard Henderson             return;
21367ec8bab3SRichard Henderson         }
21377ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
21387ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
21397ec8bab3SRichard Henderson         goto do_shift_and;
21407ec8bab3SRichard Henderson     }
21417ec8bab3SRichard Henderson 
21427ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
21437ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
21447ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
21457ec8bab3SRichard Henderson         return;
21467ec8bab3SRichard Henderson     }
21477ec8bab3SRichard Henderson 
21487ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
21497ec8bab3SRichard Henderson     switch (ofs + len) {
21507ec8bab3SRichard Henderson     case 32:
21517ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
21527ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
21537ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21547ec8bab3SRichard Henderson             return;
21557ec8bab3SRichard Henderson         }
21567ec8bab3SRichard Henderson         break;
21577ec8bab3SRichard Henderson     case 16:
21587ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
21597ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
21607ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21617ec8bab3SRichard Henderson             return;
21627ec8bab3SRichard Henderson         }
21637ec8bab3SRichard Henderson         break;
21647ec8bab3SRichard Henderson     case 8:
21657ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
21667ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
21677ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21687ec8bab3SRichard Henderson             return;
21697ec8bab3SRichard Henderson         }
21707ec8bab3SRichard Henderson         break;
21717ec8bab3SRichard Henderson     }
21727ec8bab3SRichard Henderson 
21737ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
21747ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
21757ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
21767ec8bab3SRichard Henderson     switch (len) {
21777ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
21787ec8bab3SRichard Henderson     do_shift_and:
21797ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
21807ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
21817ec8bab3SRichard Henderson         break;
21827ec8bab3SRichard Henderson     default:
21837ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
21847ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
21857ec8bab3SRichard Henderson         break;
21867ec8bab3SRichard Henderson     }
21877ec8bab3SRichard Henderson }
21887ec8bab3SRichard Henderson 
21897ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
21907ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
21917ec8bab3SRichard Henderson {
21927ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
21937ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
21947ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
21957ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
21967ec8bab3SRichard Henderson 
21977ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
21987ec8bab3SRichard Henderson     if (ofs + len == 64) {
21997ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
22007ec8bab3SRichard Henderson         return;
22017ec8bab3SRichard Henderson     }
22027ec8bab3SRichard Henderson     if (ofs == 0) {
22037ec8bab3SRichard Henderson         switch (len) {
22047ec8bab3SRichard Henderson         case 32:
22057ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22067ec8bab3SRichard Henderson             return;
22077ec8bab3SRichard Henderson         case 16:
22087ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22097ec8bab3SRichard Henderson             return;
22107ec8bab3SRichard Henderson         case 8:
22117ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22127ec8bab3SRichard Henderson             return;
22137ec8bab3SRichard Henderson         }
22147ec8bab3SRichard Henderson     }
22157ec8bab3SRichard Henderson 
22167ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22177ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22187ec8bab3SRichard Henderson         if (ofs >= 32) {
22197ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22207ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
22217ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22227ec8bab3SRichard Henderson         } else if (ofs == 0) {
22237ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
22247ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
22257ec8bab3SRichard Henderson             return;
22267ec8bab3SRichard Henderson         } else if (len > 32) {
22277ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
22287ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
22297ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
22307ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
22317ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22327ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
22337ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
22347ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
22357ec8bab3SRichard Henderson             return;
22367ec8bab3SRichard Henderson         } else {
22377ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
22387ec8bab3SRichard Henderson                field sits at the MSB.  */
22397ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
22407ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
22417ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
22427ec8bab3SRichard Henderson         }
22437ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
22447ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
22457ec8bab3SRichard Henderson         return;
22467ec8bab3SRichard Henderson     }
22477ec8bab3SRichard Henderson 
22487ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
22497ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22507ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
22517ec8bab3SRichard Henderson         return;
22527ec8bab3SRichard Henderson     }
22537ec8bab3SRichard Henderson 
22547ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
22557ec8bab3SRichard Henderson     switch (ofs + len) {
22567ec8bab3SRichard Henderson     case 32:
22577ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
22587ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22597ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22607ec8bab3SRichard Henderson             return;
22617ec8bab3SRichard Henderson         }
22627ec8bab3SRichard Henderson         break;
22637ec8bab3SRichard Henderson     case 16:
22647ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
22657ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22667ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22677ec8bab3SRichard Henderson             return;
22687ec8bab3SRichard Henderson         }
22697ec8bab3SRichard Henderson         break;
22707ec8bab3SRichard Henderson     case 8:
22717ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
22727ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22737ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22747ec8bab3SRichard Henderson             return;
22757ec8bab3SRichard Henderson         }
22767ec8bab3SRichard Henderson         break;
22777ec8bab3SRichard Henderson     }
22787ec8bab3SRichard Henderson     switch (len) {
22797ec8bab3SRichard Henderson     case 32:
22807ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
22817ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22827ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
22837ec8bab3SRichard Henderson             return;
22847ec8bab3SRichard Henderson         }
22857ec8bab3SRichard Henderson         break;
22867ec8bab3SRichard Henderson     case 16:
22877ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
22887ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22897ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
22907ec8bab3SRichard Henderson             return;
22917ec8bab3SRichard Henderson         }
22927ec8bab3SRichard Henderson         break;
22937ec8bab3SRichard Henderson     case 8:
22947ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
22957ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22967ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
22977ec8bab3SRichard Henderson             return;
22987ec8bab3SRichard Henderson         }
22997ec8bab3SRichard Henderson         break;
23007ec8bab3SRichard Henderson     }
23017ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23027ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
23037ec8bab3SRichard Henderson }
23047ec8bab3SRichard Henderson 
2305951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2306951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2307951c6300SRichard Henderson {
230837ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
230937ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
231037ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
231137ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
231237ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2313951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2314951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2315951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2316951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2317951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2318951c6300SRichard Henderson 
2319951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2320951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2321951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2322951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2323951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2324951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2325951c6300SRichard Henderson         } else {
2326951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2327951c6300SRichard Henderson 
2328951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2329951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2330951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2331951c6300SRichard Henderson 
2332951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2333951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2334951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2335951c6300SRichard Henderson         }
2336951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2337951c6300SRichard Henderson         tcg_temp_free_i32(t1);
23383a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2339951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2340951c6300SRichard Henderson     } else {
2341951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2342951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2343951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2344951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2345951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2346951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2347951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2348951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2349951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2350951c6300SRichard Henderson     }
2351951c6300SRichard Henderson }
2352951c6300SRichard Henderson 
2353951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2354951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2355951c6300SRichard Henderson {
2356951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2357951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2358951c6300SRichard Henderson     } else {
2359951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2360951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2361951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2362951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2363951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2364951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2365951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2366951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2367951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2368951c6300SRichard Henderson     }
2369951c6300SRichard Henderson }
2370951c6300SRichard Henderson 
2371951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2372951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2373951c6300SRichard Henderson {
2374951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2375951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2376951c6300SRichard Henderson     } else {
2377951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2378951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2379951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2380951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2381951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2382951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2383951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2384951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2385951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2386951c6300SRichard Henderson     }
2387951c6300SRichard Henderson }
2388951c6300SRichard Henderson 
2389951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2390951c6300SRichard Henderson {
2391951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2392951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2393951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2394951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2395951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2396951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2397951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2398951c6300SRichard Henderson         tcg_temp_free_i64(t);
2399951c6300SRichard Henderson     } else {
2400951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2401951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2402951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2403951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2404951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2405951c6300SRichard Henderson     }
2406951c6300SRichard Henderson }
2407951c6300SRichard Henderson 
2408951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2409951c6300SRichard Henderson {
2410951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2411951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2412951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2413951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2414951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2415951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2416951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2417951c6300SRichard Henderson         tcg_temp_free_i64(t);
2418951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2419951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2420951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2421951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2422951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2423951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2424951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2425951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2426951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2427951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2428951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2429951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2430951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2431951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2432951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2433951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2434951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2435951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2436951c6300SRichard Henderson     } else {
2437951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2438951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2439951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2440951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2441951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2442951c6300SRichard Henderson     }
2443951c6300SRichard Henderson }
2444951c6300SRichard Henderson 
24455087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
24465087abfbSRichard Henderson {
24475087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
24485087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
24495087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
24505087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
24515087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
24525087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
24535087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
24545087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
24555087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
24565087abfbSRichard Henderson     tcg_temp_free_i64(t0);
24575087abfbSRichard Henderson     tcg_temp_free_i64(t1);
24585087abfbSRichard Henderson     tcg_temp_free_i64(t2);
24595087abfbSRichard Henderson }
24605087abfbSRichard Henderson 
2461b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2462b87fb8cdSRichard Henderson {
2463b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2464b87fb8cdSRichard Henderson }
2465b87fb8cdSRichard Henderson 
2466b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2467b87fb8cdSRichard Henderson {
2468b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2469b87fb8cdSRichard Henderson }
2470b87fb8cdSRichard Henderson 
2471b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2472b87fb8cdSRichard Henderson {
2473b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2474b87fb8cdSRichard Henderson }
2475b87fb8cdSRichard Henderson 
2476b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2477b87fb8cdSRichard Henderson {
2478b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2479b87fb8cdSRichard Henderson }
2480b87fb8cdSRichard Henderson 
2481951c6300SRichard Henderson /* Size changing operations.  */
2482951c6300SRichard Henderson 
2483609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2484951c6300SRichard Henderson {
24853a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2486951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2487609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2488b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2489ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2490951c6300SRichard Henderson     } else {
2491dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2492609ad705SRichard Henderson     }
2493609ad705SRichard Henderson }
2494609ad705SRichard Henderson 
2495609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2496609ad705SRichard Henderson {
2497609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2498609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2499609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2500b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2501ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2502951c6300SRichard Henderson     } else {
2503951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2504609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2505dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2506951c6300SRichard Henderson         tcg_temp_free_i64(t);
2507951c6300SRichard Henderson     }
2508951c6300SRichard Henderson }
2509951c6300SRichard Henderson 
2510951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2511951c6300SRichard Henderson {
25123a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2513951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2514951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
25153a13c3f3SRichard Henderson     } else {
2516b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2517ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
25183a13c3f3SRichard Henderson     }
2519951c6300SRichard Henderson }
2520951c6300SRichard Henderson 
2521951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2522951c6300SRichard Henderson {
25233a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2524951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2525951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
25263a13c3f3SRichard Henderson     } else {
2527b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2528ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
25293a13c3f3SRichard Henderson     }
2530951c6300SRichard Henderson }
2531951c6300SRichard Henderson 
2532951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2533951c6300SRichard Henderson {
25343a13c3f3SRichard Henderson     TCGv_i64 tmp;
25353a13c3f3SRichard Henderson 
25363a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2537951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2538951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
25393a13c3f3SRichard Henderson         return;
25403a13c3f3SRichard Henderson     }
25413a13c3f3SRichard Henderson 
25423a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2543951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2544951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2545951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2546951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2547951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2548951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2549951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2550951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2551951c6300SRichard Henderson     } else {
2552951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2553951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2554951c6300SRichard Henderson     }
2555951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2556951c6300SRichard Henderson }
2557951c6300SRichard Henderson 
2558951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2559951c6300SRichard Henderson {
25603a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2561951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2562951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
25633a13c3f3SRichard Henderson     } else {
2564609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2565609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
25663a13c3f3SRichard Henderson     }
2567951c6300SRichard Henderson }
2568951c6300SRichard Henderson 
2569951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2570951c6300SRichard Henderson {
2571951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2572951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2573951c6300SRichard Henderson }
2574951c6300SRichard Henderson 
2575951c6300SRichard Henderson /* QEMU specific operations.  */
2576951c6300SRichard Henderson 
2577951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2578951c6300SRichard Henderson {
2579951c6300SRichard Henderson     /* We only support two chained exits.  */
2580951c6300SRichard Henderson     tcg_debug_assert(idx <= 1);
2581951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2582951c6300SRichard Henderson     /* Verify that we havn't seen this numbered exit before.  */
2583b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2584b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2585951c6300SRichard Henderson #endif
2586951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2587951c6300SRichard Henderson }
2588951c6300SRichard Henderson 
25897f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2590cedbcb01SEmilio G. Cota {
2591cedbcb01SEmilio G. Cota     if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
2592cedbcb01SEmilio G. Cota         TCGv_ptr ptr = tcg_temp_new_ptr();
25931c2adb95SRichard Henderson         gen_helper_lookup_tb_ptr(ptr, cpu_env);
2594ae8b75dcSRichard Henderson         tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2595cedbcb01SEmilio G. Cota         tcg_temp_free_ptr(ptr);
2596cedbcb01SEmilio G. Cota     } else {
2597cedbcb01SEmilio G. Cota         tcg_gen_exit_tb(0);
2598cedbcb01SEmilio G. Cota     }
2599cedbcb01SEmilio G. Cota }
2600cedbcb01SEmilio G. Cota 
2601951c6300SRichard Henderson static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
2602951c6300SRichard Henderson {
26031f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
26041f00b27fSSergey Sorokin     (void)get_alignment_bits(op);
26051f00b27fSSergey Sorokin 
2606951c6300SRichard Henderson     switch (op & MO_SIZE) {
2607951c6300SRichard Henderson     case MO_8:
2608951c6300SRichard Henderson         op &= ~MO_BSWAP;
2609951c6300SRichard Henderson         break;
2610951c6300SRichard Henderson     case MO_16:
2611951c6300SRichard Henderson         break;
2612951c6300SRichard Henderson     case MO_32:
2613951c6300SRichard Henderson         if (!is64) {
2614951c6300SRichard Henderson             op &= ~MO_SIGN;
2615951c6300SRichard Henderson         }
2616951c6300SRichard Henderson         break;
2617951c6300SRichard Henderson     case MO_64:
2618951c6300SRichard Henderson         if (!is64) {
2619951c6300SRichard Henderson             tcg_abort();
2620951c6300SRichard Henderson         }
2621951c6300SRichard Henderson         break;
2622951c6300SRichard Henderson     }
2623951c6300SRichard Henderson     if (st) {
2624951c6300SRichard Henderson         op &= ~MO_SIGN;
2625951c6300SRichard Henderson     }
2626951c6300SRichard Henderson     return op;
2627951c6300SRichard Henderson }
2628951c6300SRichard Henderson 
2629c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
2630c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
2631951c6300SRichard Henderson {
263259227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2633951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
263459227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2635951c6300SRichard Henderson #else
2636c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
263759227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2638c45cb8bbSRichard Henderson     } else {
2639ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2640c45cb8bbSRichard Henderson     }
2641951c6300SRichard Henderson #endif
2642c45cb8bbSRichard Henderson }
2643c45cb8bbSRichard Henderson 
2644c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
2645c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
2646c45cb8bbSRichard Henderson {
264759227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2648c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2649c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
265059227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2651c45cb8bbSRichard Henderson     } else {
2652ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2653c45cb8bbSRichard Henderson     }
2654c45cb8bbSRichard Henderson #else
2655c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
265659227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
265759227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2658c45cb8bbSRichard Henderson     } else {
265959227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2660c45cb8bbSRichard Henderson     }
2661c45cb8bbSRichard Henderson #endif
2662c45cb8bbSRichard Henderson }
2663951c6300SRichard Henderson 
2664b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2665b32dc337SPranith Kumar {
2666b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2667b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2668b32dc337SPranith Kumar #endif
2669b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2670b32dc337SPranith Kumar     if (type) {
2671b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2672b32dc337SPranith Kumar     }
2673b32dc337SPranith Kumar }
2674b32dc337SPranith Kumar 
2675951c6300SRichard Henderson void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2676951c6300SRichard Henderson {
2677b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2678951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
26791c2adb95SRichard Henderson     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
2680dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
2681c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
2682951c6300SRichard Henderson }
2683951c6300SRichard Henderson 
2684951c6300SRichard Henderson void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2685951c6300SRichard Henderson {
2686b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2687951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
26881c2adb95SRichard Henderson     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
2689dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
2690c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
2691951c6300SRichard Henderson }
2692951c6300SRichard Henderson 
2693951c6300SRichard Henderson void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2694951c6300SRichard Henderson {
2695b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
26963a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2697951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
2698951c6300SRichard Henderson         if (memop & MO_SIGN) {
2699951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
2700951c6300SRichard Henderson         } else {
2701951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
2702951c6300SRichard Henderson         }
2703951c6300SRichard Henderson         return;
2704951c6300SRichard Henderson     }
2705951c6300SRichard Henderson 
2706c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
27071c2adb95SRichard Henderson     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
2708dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
2709c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
2710951c6300SRichard Henderson }
2711951c6300SRichard Henderson 
2712951c6300SRichard Henderson void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2713951c6300SRichard Henderson {
2714b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
27153a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2716951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
2717951c6300SRichard Henderson         return;
2718951c6300SRichard Henderson     }
2719951c6300SRichard Henderson 
2720c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
27211c2adb95SRichard Henderson     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
2722dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
2723c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
2724951c6300SRichard Henderson }
2725c482cb11SRichard Henderson 
2726c482cb11SRichard Henderson static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc)
2727c482cb11SRichard Henderson {
2728c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2729c482cb11SRichard Henderson     case MO_SB:
2730c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
2731c482cb11SRichard Henderson         break;
2732c482cb11SRichard Henderson     case MO_UB:
2733c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
2734c482cb11SRichard Henderson         break;
2735c482cb11SRichard Henderson     case MO_SW:
2736c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
2737c482cb11SRichard Henderson         break;
2738c482cb11SRichard Henderson     case MO_UW:
2739c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
2740c482cb11SRichard Henderson         break;
2741c482cb11SRichard Henderson     default:
2742c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
2743c482cb11SRichard Henderson         break;
2744c482cb11SRichard Henderson     }
2745c482cb11SRichard Henderson }
2746c482cb11SRichard Henderson 
2747c482cb11SRichard Henderson static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, TCGMemOp opc)
2748c482cb11SRichard Henderson {
2749c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2750c482cb11SRichard Henderson     case MO_SB:
2751c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
2752c482cb11SRichard Henderson         break;
2753c482cb11SRichard Henderson     case MO_UB:
2754c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
2755c482cb11SRichard Henderson         break;
2756c482cb11SRichard Henderson     case MO_SW:
2757c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
2758c482cb11SRichard Henderson         break;
2759c482cb11SRichard Henderson     case MO_UW:
2760c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
2761c482cb11SRichard Henderson         break;
2762c482cb11SRichard Henderson     case MO_SL:
2763c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
2764c482cb11SRichard Henderson         break;
2765c482cb11SRichard Henderson     case MO_UL:
2766c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
2767c482cb11SRichard Henderson         break;
2768c482cb11SRichard Henderson     default:
2769c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
2770c482cb11SRichard Henderson         break;
2771c482cb11SRichard Henderson     }
2772c482cb11SRichard Henderson }
2773c482cb11SRichard Henderson 
2774c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2775c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
2776c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
2777c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
2778c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
2779c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
2780c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
2781c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
2782c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
2783c482cb11SRichard Henderson #else
2784c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
2785c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
2786c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
2787c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
2788c482cb11SRichard Henderson #endif
2789c482cb11SRichard Henderson 
2790df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2791df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
2792df79b996SRichard Henderson #else
2793df79b996SRichard Henderson # define WITH_ATOMIC64(X)
2794df79b996SRichard Henderson #endif
2795df79b996SRichard Henderson 
2796c482cb11SRichard Henderson static void * const table_cmpxchg[16] = {
2797c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
2798c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
2799c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
2800c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
2801c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
2802df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
2803df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
2804c482cb11SRichard Henderson };
2805c482cb11SRichard Henderson 
2806c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
2807c482cb11SRichard Henderson                                 TCGv_i32 newv, TCGArg idx, TCGMemOp memop)
2808c482cb11SRichard Henderson {
2809c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2810c482cb11SRichard Henderson 
2811b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
2812c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2813c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
2814c482cb11SRichard Henderson 
2815c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
2816c482cb11SRichard Henderson 
2817c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2818c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
2819c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2820c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
2821c482cb11SRichard Henderson 
2822c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2823c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
2824c482cb11SRichard Henderson         } else {
2825c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
2826c482cb11SRichard Henderson         }
2827c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
2828c482cb11SRichard Henderson     } else {
2829c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
2830c482cb11SRichard Henderson 
2831c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2832c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2833c482cb11SRichard Henderson 
2834c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2835c482cb11SRichard Henderson         {
2836c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
28371c2adb95SRichard Henderson             gen(retv, cpu_env, addr, cmpv, newv, oi);
2838c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2839c482cb11SRichard Henderson         }
2840c482cb11SRichard Henderson #else
28411c2adb95SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv);
2842c482cb11SRichard Henderson #endif
2843c482cb11SRichard Henderson 
2844c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2845c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
2846c482cb11SRichard Henderson         }
2847c482cb11SRichard Henderson     }
2848c482cb11SRichard Henderson }
2849c482cb11SRichard Henderson 
2850c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
2851c482cb11SRichard Henderson                                 TCGv_i64 newv, TCGArg idx, TCGMemOp memop)
2852c482cb11SRichard Henderson {
2853c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2854c482cb11SRichard Henderson 
2855b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
2856c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2857c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2858c482cb11SRichard Henderson 
2859c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
2860c482cb11SRichard Henderson 
2861c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2862c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
2863c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2864c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
2865c482cb11SRichard Henderson 
2866c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2867c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
2868c482cb11SRichard Henderson         } else {
2869c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
2870c482cb11SRichard Henderson         }
2871c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
2872c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
2873df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2874c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
2875c482cb11SRichard Henderson 
2876c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2877c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2878c482cb11SRichard Henderson 
2879c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2880c482cb11SRichard Henderson         {
2881c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
28821c2adb95SRichard Henderson             gen(retv, cpu_env, addr, cmpv, newv, oi);
2883c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2884c482cb11SRichard Henderson         }
2885c482cb11SRichard Henderson #else
28861c2adb95SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv);
2887c482cb11SRichard Henderson #endif
2888df79b996SRichard Henderson #else
28891c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
289079b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
289179b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
289279b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
2893df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
2894c482cb11SRichard Henderson     } else {
2895c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
2896c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
2897c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
2898c482cb11SRichard Henderson 
2899c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
2900c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
2901c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
2902c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
2903c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
2904c482cb11SRichard Henderson 
2905c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
2906c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
2907c482cb11SRichard Henderson 
2908c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2909c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
2910c482cb11SRichard Henderson         }
2911c482cb11SRichard Henderson     }
2912c482cb11SRichard Henderson }
2913c482cb11SRichard Henderson 
2914c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2915c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2916c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
2917c482cb11SRichard Henderson {
2918c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
2919c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
2920c482cb11SRichard Henderson 
2921c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2922c482cb11SRichard Henderson 
2923c482cb11SRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2924c482cb11SRichard Henderson     gen(t2, t1, val);
2925c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2926c482cb11SRichard Henderson 
2927c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
2928c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
2929c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
2930c482cb11SRichard Henderson }
2931c482cb11SRichard Henderson 
2932c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2933c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2934c482cb11SRichard Henderson {
2935c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
2936c482cb11SRichard Henderson 
2937c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2938c482cb11SRichard Henderson 
2939c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
2940c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
2941c482cb11SRichard Henderson 
2942c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2943c482cb11SRichard Henderson     {
2944c482cb11SRichard Henderson         TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
29451c2adb95SRichard Henderson         gen(ret, cpu_env, addr, val, oi);
2946c482cb11SRichard Henderson         tcg_temp_free_i32(oi);
2947c482cb11SRichard Henderson     }
2948c482cb11SRichard Henderson #else
29491c2adb95SRichard Henderson     gen(ret, cpu_env, addr, val);
2950c482cb11SRichard Henderson #endif
2951c482cb11SRichard Henderson 
2952c482cb11SRichard Henderson     if (memop & MO_SIGN) {
2953c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
2954c482cb11SRichard Henderson     }
2955c482cb11SRichard Henderson }
2956c482cb11SRichard Henderson 
2957c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2958c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2959c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
2960c482cb11SRichard Henderson {
2961c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
2962c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
2963c482cb11SRichard Henderson 
2964c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2965c482cb11SRichard Henderson 
2966c482cb11SRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2967c482cb11SRichard Henderson     gen(t2, t1, val);
2968c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2969c482cb11SRichard Henderson 
2970c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
2971c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
2972c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
2973c482cb11SRichard Henderson }
2974c482cb11SRichard Henderson 
2975c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2976c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2977c482cb11SRichard Henderson {
2978c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2979c482cb11SRichard Henderson 
2980c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
2981df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2982c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
2983c482cb11SRichard Henderson 
2984c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
2985c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2986c482cb11SRichard Henderson 
2987c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2988c482cb11SRichard Henderson         {
2989c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
29901c2adb95SRichard Henderson             gen(ret, cpu_env, addr, val, oi);
2991c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2992c482cb11SRichard Henderson         }
2993c482cb11SRichard Henderson #else
29941c2adb95SRichard Henderson         gen(ret, cpu_env, addr, val);
2995c482cb11SRichard Henderson #endif
2996df79b996SRichard Henderson #else
29971c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
299879b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
299979b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
300079b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
3001df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3002c482cb11SRichard Henderson     } else {
3003c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
3004c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3005c482cb11SRichard Henderson 
3006c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
3007c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
3008c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
3009c482cb11SRichard Henderson 
3010c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
3011c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3012c482cb11SRichard Henderson 
3013c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3014c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
3015c482cb11SRichard Henderson         }
3016c482cb11SRichard Henderson     }
3017c482cb11SRichard Henderson }
3018c482cb11SRichard Henderson 
3019c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
3020c482cb11SRichard Henderson static void * const table_##NAME[16] = {                                \
3021c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
3022c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
3023c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
3024c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
3025c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
3026df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
3027df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3028c482cb11SRichard Henderson };                                                                      \
3029c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
3030c482cb11SRichard Henderson     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \
3031c482cb11SRichard Henderson {                                                                       \
3032b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3033c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3034c482cb11SRichard Henderson     } else {                                                            \
3035c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3036c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3037c482cb11SRichard Henderson     }                                                                   \
3038c482cb11SRichard Henderson }                                                                       \
3039c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
3040c482cb11SRichard Henderson     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \
3041c482cb11SRichard Henderson {                                                                       \
3042b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3043c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3044c482cb11SRichard Henderson     } else {                                                            \
3045c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3046c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3047c482cb11SRichard Henderson     }                                                                   \
3048c482cb11SRichard Henderson }
3049c482cb11SRichard Henderson 
3050c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3051c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3052c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3053c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
3054*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smin, smin, 0)
3055*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umin, umin, 0)
3056*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smax, smax, 0)
3057*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umax, umax, 0)
3058c482cb11SRichard Henderson 
3059c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3060c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3061c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3062c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
3063*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smin_fetch, smin, 1)
3064*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umin_fetch, umin, 1)
3065*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smax_fetch, smax, 1)
3066*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umax_fetch, umax, 1)
3067c482cb11SRichard Henderson 
3068c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3069c482cb11SRichard Henderson {
3070c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3071c482cb11SRichard Henderson }
3072c482cb11SRichard Henderson 
3073c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3074c482cb11SRichard Henderson {
3075c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3076c482cb11SRichard Henderson }
3077c482cb11SRichard Henderson 
3078c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3079c482cb11SRichard Henderson 
3080c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3081