xref: /openbmc/qemu/tcg/tcg-op.c (revision 07ce0b05)
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 "cpu.h"
2763c91552SPaolo Bonzini #include "exec/exec-all.h"
28dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h"
29dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
30dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-mo.h"
31dcdaadb6SLluís Vilanova #include "trace-tcg.h"
32dcdaadb6SLluís Vilanova #include "trace/mem.h"
33e6d86bedSEmilio G. Cota #include "exec/plugin-gen.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) {
243d88a117eSRichard Henderson         l->refs++;
24442a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
245951c6300SRichard Henderson     }
246951c6300SRichard Henderson }
247951c6300SRichard Henderson 
24842a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
249951c6300SRichard Henderson {
25037ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
25137ed3bf1SRichard Henderson         tcg_gen_br(l);
25237ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
253951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
25442a268c2SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, t0, l);
255951c6300SRichard Henderson         tcg_temp_free_i32(t0);
256951c6300SRichard Henderson     }
25737ed3bf1SRichard Henderson }
258951c6300SRichard Henderson 
259951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
260951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
261951c6300SRichard Henderson {
262951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
263951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
264951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
265951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
266951c6300SRichard Henderson     } else {
267951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
268951c6300SRichard Henderson     }
269951c6300SRichard Henderson }
270951c6300SRichard Henderson 
271951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
272951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
273951c6300SRichard Henderson {
274951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
275951c6300SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, t0);
276951c6300SRichard Henderson     tcg_temp_free_i32(t0);
277951c6300SRichard Henderson }
278951c6300SRichard Henderson 
279951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
280951c6300SRichard Henderson {
281b2e3ae94SRichard Henderson     if (arg2 == 0) {
282b2e3ae94SRichard Henderson         tcg_gen_movi_i32(ret, 0);
283b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
284b2e3ae94SRichard Henderson         tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
285b2e3ae94SRichard Henderson     } else {
286951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
287951c6300SRichard Henderson         tcg_gen_mul_i32(ret, arg1, t0);
288951c6300SRichard Henderson         tcg_temp_free_i32(t0);
289951c6300SRichard Henderson     }
290b2e3ae94SRichard Henderson }
291951c6300SRichard Henderson 
292951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
293951c6300SRichard Henderson {
294951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
295951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
296951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
297951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
298951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
299951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
300951c6300SRichard Henderson         tcg_temp_free_i32(t0);
301951c6300SRichard Henderson     } else {
302951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
303951c6300SRichard Henderson     }
304951c6300SRichard Henderson }
305951c6300SRichard Henderson 
306951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
307951c6300SRichard Henderson {
308951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
309951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
310951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
311951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
312951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
313951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
314951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
315951c6300SRichard Henderson         tcg_temp_free_i32(t0);
316951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
317951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
318951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
319951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
320951c6300SRichard Henderson         tcg_temp_free_i32(t0);
321951c6300SRichard Henderson     } else {
322951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
323951c6300SRichard Henderson     }
324951c6300SRichard Henderson }
325951c6300SRichard Henderson 
326951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
327951c6300SRichard Henderson {
328951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
329951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
330951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
331951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
332951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
333951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
334951c6300SRichard Henderson         tcg_temp_free_i32(t0);
335951c6300SRichard Henderson     } else {
336951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
337951c6300SRichard Henderson     }
338951c6300SRichard Henderson }
339951c6300SRichard Henderson 
340951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
341951c6300SRichard Henderson {
342951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
343951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
344951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
345951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
346951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
347951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
348951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
349951c6300SRichard Henderson         tcg_temp_free_i32(t0);
350951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
351951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
352951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
353951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
354951c6300SRichard Henderson         tcg_temp_free_i32(t0);
355951c6300SRichard Henderson     } else {
356951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
357951c6300SRichard Henderson     }
358951c6300SRichard Henderson }
359951c6300SRichard Henderson 
360951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
361951c6300SRichard Henderson {
362951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
363951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
364951c6300SRichard Henderson     } else {
365951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
366951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
367951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
368951c6300SRichard Henderson         tcg_temp_free_i32(t0);
369951c6300SRichard Henderson     }
370951c6300SRichard Henderson }
371951c6300SRichard Henderson 
372951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
373951c6300SRichard Henderson {
374951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
375951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
376951c6300SRichard Henderson     } else {
377951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
378951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
379951c6300SRichard Henderson     }
380951c6300SRichard Henderson }
381951c6300SRichard Henderson 
382951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
383951c6300SRichard Henderson {
384951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
385951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
386951c6300SRichard Henderson     } else {
387951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
388951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
389951c6300SRichard Henderson     }
390951c6300SRichard Henderson }
391951c6300SRichard Henderson 
392951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
393951c6300SRichard Henderson {
394951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
395951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
396951c6300SRichard Henderson     } else {
397951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
398951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
399951c6300SRichard Henderson     }
400951c6300SRichard Henderson }
401951c6300SRichard Henderson 
402951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
403951c6300SRichard Henderson {
404951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
405951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
406951c6300SRichard Henderson     } else {
407951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
408951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
409951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
410951c6300SRichard Henderson         tcg_temp_free_i32(t0);
411951c6300SRichard Henderson     }
412951c6300SRichard Henderson }
413951c6300SRichard Henderson 
4140e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4150e28d006SRichard Henderson {
4160e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4170e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
4180e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
4190e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4200e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4210e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4220e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4230e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4240e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4250e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4260e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4270e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4280e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4290e28d006SRichard Henderson     } else {
4300e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4310e28d006SRichard Henderson     }
4320e28d006SRichard Henderson }
4330e28d006SRichard Henderson 
4340e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4350e28d006SRichard Henderson {
4360e28d006SRichard Henderson     TCGv_i32 t = tcg_const_i32(arg2);
4370e28d006SRichard Henderson     tcg_gen_clz_i32(ret, arg1, t);
4380e28d006SRichard Henderson     tcg_temp_free_i32(t);
4390e28d006SRichard Henderson }
4400e28d006SRichard Henderson 
4410e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4420e28d006SRichard Henderson {
4430e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4440e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4450e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4460e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4470e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4480e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4490e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4500e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4510e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4520e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4530e28d006SRichard Henderson         tcg_temp_free_i64(t2);
45414e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
45514e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
45614e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
45714e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
45814e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
45914e99210SRichard Henderson 
46014e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
46114e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
46214e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
46314e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
46414e99210SRichard Henderson         } else {
46514e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
46614e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
46714e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
46814e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
46914e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
47014e99210SRichard Henderson         }
47114e99210SRichard Henderson         z = tcg_const_i32(0);
47214e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
47314e99210SRichard Henderson         tcg_temp_free_i32(t);
47414e99210SRichard Henderson         tcg_temp_free_i32(z);
4750e28d006SRichard Henderson     } else {
4760e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4770e28d006SRichard Henderson     }
4780e28d006SRichard Henderson }
4790e28d006SRichard Henderson 
4800e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4810e28d006SRichard Henderson {
48214e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
48314e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
48414e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
48514e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
48614e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
48714e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
48814e99210SRichard Henderson         tcg_temp_free_i32(t);
48914e99210SRichard Henderson     } else {
4900e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32(arg2);
4910e28d006SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, t);
4920e28d006SRichard Henderson         tcg_temp_free_i32(t);
4930e28d006SRichard Henderson     }
49414e99210SRichard Henderson }
4950e28d006SRichard Henderson 
496086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
497086920c2SRichard Henderson {
498086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
499086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
500086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
501086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
502086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
503086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
504086920c2SRichard Henderson         tcg_temp_free_i32(t);
505086920c2SRichard Henderson     } else {
506086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
507086920c2SRichard Henderson     }
508086920c2SRichard Henderson }
509086920c2SRichard Henderson 
510a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
511a768e4e9SRichard Henderson {
512a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
513a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
514a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
515a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
516a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
517a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
518a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
519a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
520a768e4e9SRichard Henderson     } else {
521a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
522a768e4e9SRichard Henderson     }
523a768e4e9SRichard Henderson }
524a768e4e9SRichard Henderson 
525951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
526951c6300SRichard Henderson {
527951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
528951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
529951c6300SRichard Henderson     } else {
530951c6300SRichard Henderson         TCGv_i32 t0, t1;
531951c6300SRichard Henderson 
532951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
533951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
534951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
535951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
536951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
537951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
538951c6300SRichard Henderson         tcg_temp_free_i32(t0);
539951c6300SRichard Henderson         tcg_temp_free_i32(t1);
540951c6300SRichard Henderson     }
541951c6300SRichard Henderson }
542951c6300SRichard Henderson 
54307dada03SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
544951c6300SRichard Henderson {
54507dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
546951c6300SRichard Henderson     /* some cases can be optimized here */
547951c6300SRichard Henderson     if (arg2 == 0) {
548951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
549951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
550951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
551951c6300SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, t0);
552951c6300SRichard Henderson         tcg_temp_free_i32(t0);
553951c6300SRichard Henderson     } else {
554951c6300SRichard Henderson         TCGv_i32 t0, t1;
555951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
556951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
557951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
558951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
559951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
560951c6300SRichard Henderson         tcg_temp_free_i32(t0);
561951c6300SRichard Henderson         tcg_temp_free_i32(t1);
562951c6300SRichard Henderson     }
563951c6300SRichard Henderson }
564951c6300SRichard Henderson 
565951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
566951c6300SRichard Henderson {
567951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
568951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
569951c6300SRichard Henderson     } else {
570951c6300SRichard Henderson         TCGv_i32 t0, t1;
571951c6300SRichard Henderson 
572951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
573951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
574951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
575951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
576951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
577951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
578951c6300SRichard Henderson         tcg_temp_free_i32(t0);
579951c6300SRichard Henderson         tcg_temp_free_i32(t1);
580951c6300SRichard Henderson     }
581951c6300SRichard Henderson }
582951c6300SRichard Henderson 
58307dada03SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
584951c6300SRichard Henderson {
58507dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 32);
586951c6300SRichard Henderson     /* some cases can be optimized here */
587951c6300SRichard Henderson     if (arg2 == 0) {
588951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
589951c6300SRichard Henderson     } else {
590951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
591951c6300SRichard Henderson     }
592951c6300SRichard Henderson }
593951c6300SRichard Henderson 
594951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
595951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
596951c6300SRichard Henderson {
597951c6300SRichard Henderson     uint32_t mask;
598951c6300SRichard Henderson     TCGv_i32 t1;
599951c6300SRichard Henderson 
600951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
6010d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
602951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
603951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
604951c6300SRichard Henderson 
6050d0d309dSRichard Henderson     if (len == 32) {
606951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
607951c6300SRichard Henderson         return;
608951c6300SRichard Henderson     }
609951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
610951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
611951c6300SRichard Henderson         return;
612951c6300SRichard Henderson     }
613951c6300SRichard Henderson 
614951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
615951c6300SRichard Henderson 
616b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i32) {
617b0a60567SRichard Henderson         if (ofs + len == 32) {
618b0a60567SRichard Henderson             tcg_gen_shli_i32(t1, arg1, len);
619b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, t1, arg2, len);
620b0a60567SRichard Henderson             goto done;
621b0a60567SRichard Henderson         }
622b0a60567SRichard Henderson         if (ofs == 0) {
623b0a60567SRichard Henderson             tcg_gen_extract2_i32(ret, arg1, arg2, len);
624b0a60567SRichard Henderson             tcg_gen_rotli_i32(ret, ret, len);
625b0a60567SRichard Henderson             goto done;
626b0a60567SRichard Henderson         }
627b0a60567SRichard Henderson     }
628b0a60567SRichard Henderson 
629b0a60567SRichard Henderson     mask = (1u << len) - 1;
630951c6300SRichard Henderson     if (ofs + len < 32) {
631951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
632951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
633951c6300SRichard Henderson     } else {
634951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
635951c6300SRichard Henderson     }
636951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
637951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
638b0a60567SRichard Henderson  done:
639951c6300SRichard Henderson     tcg_temp_free_i32(t1);
640951c6300SRichard Henderson }
641951c6300SRichard Henderson 
64207cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
64307cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
64407cc68d5SRichard Henderson {
64507cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
64607cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
64707cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
64807cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
64907cc68d5SRichard Henderson 
65007cc68d5SRichard Henderson     if (ofs + len == 32) {
65107cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
65207cc68d5SRichard Henderson     } else if (ofs == 0) {
65307cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
65407cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
65507cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
65607cc68d5SRichard Henderson         TCGv_i32 zero = tcg_const_i32(0);
65707cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
65807cc68d5SRichard Henderson         tcg_temp_free_i32(zero);
65907cc68d5SRichard Henderson     } else {
66007cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
66107cc68d5SRichard Henderson            which allows ARG to stay live.  */
66207cc68d5SRichard Henderson         switch (len) {
66307cc68d5SRichard Henderson         case 16:
66407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
66507cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
66607cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
66707cc68d5SRichard Henderson                 return;
66807cc68d5SRichard Henderson             }
66907cc68d5SRichard Henderson             break;
67007cc68d5SRichard Henderson         case 8:
67107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
67207cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
67307cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
67407cc68d5SRichard Henderson                 return;
67507cc68d5SRichard Henderson             }
67607cc68d5SRichard Henderson             break;
67707cc68d5SRichard Henderson         }
67807cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
67907cc68d5SRichard Henderson         switch (ofs + len) {
68007cc68d5SRichard Henderson         case 16:
68107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
68207cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
68307cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
68407cc68d5SRichard Henderson                 return;
68507cc68d5SRichard Henderson             }
68607cc68d5SRichard Henderson             break;
68707cc68d5SRichard Henderson         case 8:
68807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
68907cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
69007cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
69107cc68d5SRichard Henderson                 return;
69207cc68d5SRichard Henderson             }
69307cc68d5SRichard Henderson             break;
69407cc68d5SRichard Henderson         }
69507cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
69607cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
69707cc68d5SRichard Henderson     }
69807cc68d5SRichard Henderson }
69907cc68d5SRichard Henderson 
7007ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
7017ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
7027ec8bab3SRichard Henderson {
7037ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7047ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7057ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7067ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7077ec8bab3SRichard Henderson 
7087ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7097ec8bab3SRichard Henderson     if (ofs + len == 32) {
7107ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
7117ec8bab3SRichard Henderson         return;
7127ec8bab3SRichard Henderson     }
7137ec8bab3SRichard Henderson     if (ofs == 0) {
7147ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
7157ec8bab3SRichard Henderson         return;
7167ec8bab3SRichard Henderson     }
7177ec8bab3SRichard Henderson 
7187ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
7197ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7207ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
7217ec8bab3SRichard Henderson         return;
7227ec8bab3SRichard Henderson     }
7237ec8bab3SRichard Henderson 
7247ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
7257ec8bab3SRichard Henderson     switch (ofs + len) {
7267ec8bab3SRichard Henderson     case 16:
7277ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7287ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7297ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7307ec8bab3SRichard Henderson             return;
7317ec8bab3SRichard Henderson         }
7327ec8bab3SRichard Henderson         break;
7337ec8bab3SRichard Henderson     case 8:
7347ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7357ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7367ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7377ec8bab3SRichard Henderson             return;
7387ec8bab3SRichard Henderson         }
7397ec8bab3SRichard Henderson         break;
7407ec8bab3SRichard Henderson     }
7417ec8bab3SRichard Henderson 
7427ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7437ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7447ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7457ec8bab3SRichard Henderson     switch (len) {
7467ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7477ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7487ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7497ec8bab3SRichard Henderson         break;
7507ec8bab3SRichard Henderson     default:
7517ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7527ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7537ec8bab3SRichard Henderson         break;
7547ec8bab3SRichard Henderson     }
7557ec8bab3SRichard Henderson }
7567ec8bab3SRichard Henderson 
7577ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7587ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7597ec8bab3SRichard Henderson {
7607ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7617ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7627ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7637ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7647ec8bab3SRichard Henderson 
7657ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7667ec8bab3SRichard Henderson     if (ofs + len == 32) {
7677ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7687ec8bab3SRichard Henderson         return;
7697ec8bab3SRichard Henderson     }
7707ec8bab3SRichard Henderson     if (ofs == 0) {
7717ec8bab3SRichard Henderson         switch (len) {
7727ec8bab3SRichard Henderson         case 16:
7737ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7747ec8bab3SRichard Henderson             return;
7757ec8bab3SRichard Henderson         case 8:
7767ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7777ec8bab3SRichard Henderson             return;
7787ec8bab3SRichard Henderson         }
7797ec8bab3SRichard Henderson     }
7807ec8bab3SRichard Henderson 
7817ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7827ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7837ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7847ec8bab3SRichard Henderson         return;
7857ec8bab3SRichard Henderson     }
7867ec8bab3SRichard Henderson 
7877ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7887ec8bab3SRichard Henderson     switch (ofs + len) {
7897ec8bab3SRichard Henderson     case 16:
7907ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7917ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7927ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7937ec8bab3SRichard Henderson             return;
7947ec8bab3SRichard Henderson         }
7957ec8bab3SRichard Henderson         break;
7967ec8bab3SRichard Henderson     case 8:
7977ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
7987ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7997ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
8007ec8bab3SRichard Henderson             return;
8017ec8bab3SRichard Henderson         }
8027ec8bab3SRichard Henderson         break;
8037ec8bab3SRichard Henderson     }
8047ec8bab3SRichard Henderson     switch (len) {
8057ec8bab3SRichard Henderson     case 16:
8067ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
8077ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8087ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
8097ec8bab3SRichard Henderson             return;
8107ec8bab3SRichard Henderson         }
8117ec8bab3SRichard Henderson         break;
8127ec8bab3SRichard Henderson     case 8:
8137ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8147ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8157ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
8167ec8bab3SRichard Henderson             return;
8177ec8bab3SRichard Henderson         }
8187ec8bab3SRichard Henderson         break;
8197ec8bab3SRichard Henderson     }
8207ec8bab3SRichard Henderson 
8217ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
8227ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
8237ec8bab3SRichard Henderson }
8247ec8bab3SRichard Henderson 
8252089fcc9SDavid Hildenbrand /*
8262089fcc9SDavid Hildenbrand  * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
8272089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
8282089fcc9SDavid Hildenbrand  */
8292089fcc9SDavid Hildenbrand void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
8302089fcc9SDavid Hildenbrand                           unsigned int ofs)
8312089fcc9SDavid Hildenbrand {
8322089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 32);
8332089fcc9SDavid Hildenbrand     if (ofs == 0) {
8342089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, al);
8352089fcc9SDavid Hildenbrand     } else if (ofs == 32) {
8362089fcc9SDavid Hildenbrand         tcg_gen_mov_i32(ret, ah);
8372089fcc9SDavid Hildenbrand     } else if (al == ah) {
8382089fcc9SDavid Hildenbrand         tcg_gen_rotri_i32(ret, al, ofs);
839fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i32) {
840fce1296fSRichard Henderson         tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
8412089fcc9SDavid Hildenbrand     } else {
8422089fcc9SDavid Hildenbrand         TCGv_i32 t0 = tcg_temp_new_i32();
8432089fcc9SDavid Hildenbrand         tcg_gen_shri_i32(t0, al, ofs);
8442089fcc9SDavid Hildenbrand         tcg_gen_deposit_i32(ret, t0, ah, 32 - ofs, ofs);
8452089fcc9SDavid Hildenbrand         tcg_temp_free_i32(t0);
8462089fcc9SDavid Hildenbrand     }
8472089fcc9SDavid Hildenbrand }
8482089fcc9SDavid Hildenbrand 
849951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
850951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
851951c6300SRichard Henderson {
85237ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
85337ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
85437ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
85537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
85637ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
857951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
858951c6300SRichard Henderson     } else {
859951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
860951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
861951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
862951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
863951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
864951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
865951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
866951c6300SRichard Henderson         tcg_temp_free_i32(t0);
867951c6300SRichard Henderson         tcg_temp_free_i32(t1);
868951c6300SRichard Henderson     }
869951c6300SRichard Henderson }
870951c6300SRichard Henderson 
871951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
872951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
873951c6300SRichard Henderson {
874951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
875951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
876951c6300SRichard Henderson     } else {
877951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
878951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
879951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
880951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
881951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
882951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
883951c6300SRichard Henderson         tcg_temp_free_i64(t0);
884951c6300SRichard Henderson         tcg_temp_free_i64(t1);
885951c6300SRichard Henderson     }
886951c6300SRichard Henderson }
887951c6300SRichard Henderson 
888951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
889951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
890951c6300SRichard Henderson {
891951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
892951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
893951c6300SRichard Henderson     } else {
894951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
895951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
896951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
897951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
898951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
899951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
900951c6300SRichard Henderson         tcg_temp_free_i64(t0);
901951c6300SRichard Henderson         tcg_temp_free_i64(t1);
902951c6300SRichard Henderson     }
903951c6300SRichard Henderson }
904951c6300SRichard Henderson 
905951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
906951c6300SRichard Henderson {
907951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
908951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
909951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
910951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
911951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
912951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
913951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
914951c6300SRichard Henderson         tcg_temp_free_i32(t);
915951c6300SRichard Henderson     } else {
916951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
917951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
918951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
919951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
920951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
921951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
922951c6300SRichard Henderson         tcg_temp_free_i64(t0);
923951c6300SRichard Henderson         tcg_temp_free_i64(t1);
924951c6300SRichard Henderson     }
925951c6300SRichard Henderson }
926951c6300SRichard Henderson 
927951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
928951c6300SRichard Henderson {
929951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
930951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
931951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
932951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
933951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
934951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
935951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
936951c6300SRichard Henderson         tcg_temp_free_i32(t);
937951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
938951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
939951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
940951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
941951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
942951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
943951c6300SRichard Henderson         /* Adjust for negative inputs.  */
944951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
945951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
946951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
947951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
948951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
949951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
950951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
951951c6300SRichard Henderson         tcg_temp_free_i32(t0);
952951c6300SRichard Henderson         tcg_temp_free_i32(t1);
953951c6300SRichard Henderson         tcg_temp_free_i32(t2);
954951c6300SRichard Henderson         tcg_temp_free_i32(t3);
955951c6300SRichard Henderson     } else {
956951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
957951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
958951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
959951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
960951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
961951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
962951c6300SRichard Henderson         tcg_temp_free_i64(t0);
963951c6300SRichard Henderson         tcg_temp_free_i64(t1);
964951c6300SRichard Henderson     }
965951c6300SRichard Henderson }
966951c6300SRichard Henderson 
9675087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9685087abfbSRichard Henderson {
9695087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9705087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9715087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9725087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9735087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9745087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9755087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9765087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9775087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9785087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9795087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9805087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9815087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9825087abfbSRichard Henderson     } else {
9835087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9845087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9855087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9865087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9875087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9885087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9895087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9905087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9915087abfbSRichard Henderson     }
9925087abfbSRichard Henderson }
9935087abfbSRichard Henderson 
994951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
995951c6300SRichard Henderson {
996951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
997951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
998951c6300SRichard Henderson     } else {
999951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
1000951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
1001951c6300SRichard Henderson     }
1002951c6300SRichard Henderson }
1003951c6300SRichard Henderson 
1004951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
1005951c6300SRichard Henderson {
1006951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
1007951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
1008951c6300SRichard Henderson     } else {
1009951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
1010951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
1011951c6300SRichard Henderson     }
1012951c6300SRichard Henderson }
1013951c6300SRichard Henderson 
1014951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
1015951c6300SRichard Henderson {
1016951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
1017951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
1018951c6300SRichard Henderson     } else {
1019951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
1020951c6300SRichard Henderson     }
1021951c6300SRichard Henderson }
1022951c6300SRichard Henderson 
1023951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
1024951c6300SRichard Henderson {
1025951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
1026951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
1027951c6300SRichard Henderson     } else {
1028951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1029951c6300SRichard Henderson     }
1030951c6300SRichard Henderson }
1031951c6300SRichard Henderson 
1032951c6300SRichard Henderson /* Note: we assume the two high bytes are set to zero */
1033951c6300SRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
1034951c6300SRichard Henderson {
1035951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
1036951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
1037951c6300SRichard Henderson     } else {
1038951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1039951c6300SRichard Henderson 
1040951c6300SRichard Henderson         tcg_gen_ext8u_i32(t0, arg);
1041951c6300SRichard Henderson         tcg_gen_shli_i32(t0, t0, 8);
1042951c6300SRichard Henderson         tcg_gen_shri_i32(ret, arg, 8);
1043951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t0);
1044951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1045951c6300SRichard Henderson     }
1046951c6300SRichard Henderson }
1047951c6300SRichard Henderson 
1048951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1049951c6300SRichard Henderson {
1050951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1051951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
1052951c6300SRichard Henderson     } else {
1053a686dc71SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1054a686dc71SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
1055a686dc71SRichard Henderson         TCGv_i32 t2 = tcg_const_i32(0x00ff00ff);
1056951c6300SRichard Henderson 
1057a686dc71SRichard Henderson                                         /* arg = abcd */
1058a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, arg, 8);   /*  t0 = .abc */
1059a686dc71SRichard Henderson         tcg_gen_and_i32(t1, arg, t2);   /*  t1 = .b.d */
1060a686dc71SRichard Henderson         tcg_gen_and_i32(t0, t0, t2);    /*  t0 = .a.c */
1061a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);    /*  t1 = b.d. */
1062a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = badc */
1063951c6300SRichard Henderson 
1064a686dc71SRichard Henderson         tcg_gen_shri_i32(t0, ret, 16);  /*  t0 = ..ba */
1065a686dc71SRichard Henderson         tcg_gen_shli_i32(t1, ret, 16);  /*  t1 = dc.. */
1066a686dc71SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);    /* ret = dcba */
1067951c6300SRichard Henderson 
1068951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1069951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1070a686dc71SRichard Henderson         tcg_temp_free_i32(t2);
1071951c6300SRichard Henderson     }
1072951c6300SRichard Henderson }
1073951c6300SRichard Henderson 
1074b87fb8cdSRichard Henderson void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1075b87fb8cdSRichard Henderson {
1076b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
1077b87fb8cdSRichard Henderson }
1078b87fb8cdSRichard Henderson 
1079b87fb8cdSRichard Henderson void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1080b87fb8cdSRichard Henderson {
1081b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
1082b87fb8cdSRichard Henderson }
1083b87fb8cdSRichard Henderson 
1084b87fb8cdSRichard Henderson void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1085b87fb8cdSRichard Henderson {
1086b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
1087b87fb8cdSRichard Henderson }
1088b87fb8cdSRichard Henderson 
1089b87fb8cdSRichard Henderson void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
1090b87fb8cdSRichard Henderson {
1091b87fb8cdSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
1092b87fb8cdSRichard Henderson }
1093b87fb8cdSRichard Henderson 
1094ff1f11f7SRichard Henderson void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
1095ff1f11f7SRichard Henderson {
1096ff1f11f7SRichard Henderson     TCGv_i32 t = tcg_temp_new_i32();
1097ff1f11f7SRichard Henderson 
1098ff1f11f7SRichard Henderson     tcg_gen_sari_i32(t, a, 31);
1099ff1f11f7SRichard Henderson     tcg_gen_xor_i32(ret, a, t);
1100ff1f11f7SRichard Henderson     tcg_gen_sub_i32(ret, ret, t);
1101ff1f11f7SRichard Henderson     tcg_temp_free_i32(t);
1102ff1f11f7SRichard Henderson }
1103ff1f11f7SRichard Henderson 
1104951c6300SRichard Henderson /* 64-bit ops */
1105951c6300SRichard Henderson 
1106951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1107951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1108951c6300SRichard Henderson 
1109951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1110951c6300SRichard Henderson {
1111951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1112951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1113951c6300SRichard Henderson }
1114951c6300SRichard Henderson 
1115951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1116951c6300SRichard Henderson {
1117951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1118951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1119951c6300SRichard Henderson }
1120951c6300SRichard Henderson 
1121951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1122951c6300SRichard Henderson {
1123951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1124951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1125951c6300SRichard Henderson }
1126951c6300SRichard Henderson 
1127951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1128951c6300SRichard Henderson {
1129951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1130951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1131951c6300SRichard Henderson }
1132951c6300SRichard Henderson 
1133951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1134951c6300SRichard Henderson {
1135951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11363ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1137951c6300SRichard Henderson }
1138951c6300SRichard Henderson 
1139951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1140951c6300SRichard Henderson {
1141951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1142951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1143951c6300SRichard Henderson }
1144951c6300SRichard Henderson 
1145951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1146951c6300SRichard Henderson {
1147951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1148951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1149951c6300SRichard Henderson }
1150951c6300SRichard Henderson 
1151951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1152951c6300SRichard Henderson {
1153951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1154951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1155951c6300SRichard Henderson }
1156951c6300SRichard Henderson 
1157951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1158951c6300SRichard Henderson {
1159951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1160951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1161951c6300SRichard Henderson }
1162951c6300SRichard Henderson 
1163951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1164951c6300SRichard Henderson {
1165951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1166951c6300SRichard Henderson        they cannot be the same temporary */
1167cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1168951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1169951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1170951c6300SRichard Henderson #else
1171951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1172951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1173951c6300SRichard Henderson #endif
1174951c6300SRichard Henderson }
1175951c6300SRichard Henderson 
1176951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1177951c6300SRichard Henderson {
1178cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1179951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1180951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1181951c6300SRichard Henderson #else
1182951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1183951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1184951c6300SRichard Henderson #endif
1185951c6300SRichard Henderson }
1186951c6300SRichard Henderson 
1187951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1188951c6300SRichard Henderson {
1189951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1190951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1191951c6300SRichard Henderson }
1192951c6300SRichard Henderson 
1193951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1194951c6300SRichard Henderson {
1195951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1196951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1197951c6300SRichard Henderson }
1198951c6300SRichard Henderson 
1199951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1200951c6300SRichard Henderson {
1201951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1202951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1203951c6300SRichard Henderson }
1204951c6300SRichard Henderson 
1205951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1206951c6300SRichard Henderson {
1207951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1208951c6300SRichard Henderson }
1209951c6300SRichard Henderson 
1210951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1211951c6300SRichard Henderson {
1212951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1213951c6300SRichard Henderson }
1214951c6300SRichard Henderson 
1215951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1216951c6300SRichard Henderson {
1217951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1218951c6300SRichard Henderson }
1219951c6300SRichard Henderson 
1220951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1221951c6300SRichard Henderson {
1222951c6300SRichard Henderson     TCGv_i64 t0;
1223951c6300SRichard Henderson     TCGv_i32 t1;
1224951c6300SRichard Henderson 
1225951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1226951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1227951c6300SRichard Henderson 
1228951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1229951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1230951c6300SRichard Henderson 
1231951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1232951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1233951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1234951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1235951c6300SRichard Henderson 
1236951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1237951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1238951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1239951c6300SRichard Henderson }
1240951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1241951c6300SRichard Henderson 
1242951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1243951c6300SRichard Henderson {
1244951c6300SRichard Henderson     /* some cases can be optimized here */
1245951c6300SRichard Henderson     if (arg2 == 0) {
1246951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1247951c6300SRichard Henderson     } else {
1248951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1249951c6300SRichard Henderson         tcg_gen_add_i64(ret, arg1, t0);
1250951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1251951c6300SRichard Henderson     }
1252951c6300SRichard Henderson }
1253951c6300SRichard Henderson 
1254951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1255951c6300SRichard Henderson {
1256951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1257951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1258951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
1259951c6300SRichard Henderson     } else {
1260951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg1);
1261951c6300SRichard Henderson         tcg_gen_sub_i64(ret, t0, arg2);
1262951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1263951c6300SRichard Henderson     }
1264951c6300SRichard Henderson }
1265951c6300SRichard Henderson 
1266951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1267951c6300SRichard Henderson {
1268951c6300SRichard Henderson     /* some cases can be optimized here */
1269951c6300SRichard Henderson     if (arg2 == 0) {
1270951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1271951c6300SRichard Henderson     } else {
1272951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1273951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1274951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1275951c6300SRichard Henderson     }
1276951c6300SRichard Henderson }
1277951c6300SRichard Henderson 
1278474b2e8fSRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1279951c6300SRichard Henderson {
12803a13c3f3SRichard Henderson     TCGv_i64 t0;
12813a13c3f3SRichard Henderson 
12823a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1283951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1284951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12853a13c3f3SRichard Henderson         return;
12863a13c3f3SRichard Henderson     }
12873a13c3f3SRichard Henderson 
1288951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1289951c6300SRichard Henderson     switch (arg2) {
1290951c6300SRichard Henderson     case 0:
1291951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1292951c6300SRichard Henderson         return;
1293474b2e8fSRichard Henderson     case -1:
1294951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1295951c6300SRichard Henderson         return;
1296474b2e8fSRichard Henderson     case 0xff:
1297951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1298951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1299951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1300951c6300SRichard Henderson             return;
1301951c6300SRichard Henderson         }
1302951c6300SRichard Henderson         break;
1303474b2e8fSRichard Henderson     case 0xffff:
1304951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1305951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1306951c6300SRichard Henderson             return;
1307951c6300SRichard Henderson         }
1308951c6300SRichard Henderson         break;
1309474b2e8fSRichard Henderson     case 0xffffffffu:
1310951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1311951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1312951c6300SRichard Henderson             return;
1313951c6300SRichard Henderson         }
1314951c6300SRichard Henderson         break;
1315951c6300SRichard Henderson     }
1316951c6300SRichard Henderson     t0 = tcg_const_i64(arg2);
1317951c6300SRichard Henderson     tcg_gen_and_i64(ret, arg1, t0);
1318951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1319951c6300SRichard Henderson }
1320951c6300SRichard Henderson 
1321951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1322951c6300SRichard Henderson {
13233a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1324951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1325951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13263a13c3f3SRichard Henderson         return;
13273a13c3f3SRichard Henderson     }
1328951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1329951c6300SRichard Henderson     if (arg2 == -1) {
1330951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1331951c6300SRichard Henderson     } else if (arg2 == 0) {
1332951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1333951c6300SRichard Henderson     } else {
1334951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1335951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1336951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1337951c6300SRichard Henderson     }
1338951c6300SRichard Henderson }
1339951c6300SRichard Henderson 
1340951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1341951c6300SRichard Henderson {
13423a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1343951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1344951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13453a13c3f3SRichard Henderson         return;
13463a13c3f3SRichard Henderson     }
1347951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1348951c6300SRichard Henderson     if (arg2 == 0) {
1349951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1350951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1351951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1352951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1353951c6300SRichard Henderson     } else {
1354951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1355951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, t0);
1356951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1357951c6300SRichard Henderson     }
1358951c6300SRichard Henderson }
1359951c6300SRichard Henderson 
1360951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1361951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1362951c6300SRichard Henderson {
1363951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1364951c6300SRichard Henderson     if (c == 0) {
1365951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1366951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1367951c6300SRichard Henderson     } else if (c >= 32) {
1368951c6300SRichard Henderson         c -= 32;
1369951c6300SRichard Henderson         if (right) {
1370951c6300SRichard Henderson             if (arith) {
1371951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1372951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1373951c6300SRichard Henderson             } else {
1374951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1375951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1376951c6300SRichard Henderson             }
1377951c6300SRichard Henderson         } else {
1378951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1379951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1380951c6300SRichard Henderson         }
138102616badSRichard Henderson     } else if (right) {
138202616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
138302616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_LOW(ret),
138402616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1385951c6300SRichard Henderson         } else {
1386951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
138702616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(ret),
138802616badSRichard Henderson                                 TCGV_HIGH(arg1), 32 - c, c);
1389951c6300SRichard Henderson         }
139002616badSRichard Henderson         if (arith) {
139102616badSRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
139202616badSRichard Henderson         } else {
139302616badSRichard Henderson             tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
139402616badSRichard Henderson         }
139502616badSRichard Henderson     } else {
139602616badSRichard Henderson         if (TCG_TARGET_HAS_extract2_i32) {
139702616badSRichard Henderson             tcg_gen_extract2_i32(TCGV_HIGH(ret),
139802616badSRichard Henderson                                  TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
139902616badSRichard Henderson         } else {
140002616badSRichard Henderson             TCGv_i32 t0 = tcg_temp_new_i32();
140102616badSRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
140202616badSRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), t0,
140302616badSRichard Henderson                                 TCGV_HIGH(arg1), c, 32 - c);
1404951c6300SRichard Henderson             tcg_temp_free_i32(t0);
140502616badSRichard Henderson         }
140602616badSRichard Henderson         tcg_gen_shli_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1407951c6300SRichard Henderson     }
1408951c6300SRichard Henderson }
1409951c6300SRichard Henderson 
1410474b2e8fSRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1411951c6300SRichard Henderson {
1412474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14143a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
14153a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1416951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1417951c6300SRichard Henderson     } else {
1418951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1419951c6300SRichard Henderson         tcg_gen_shl_i64(ret, arg1, t0);
1420951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1421951c6300SRichard Henderson     }
1422951c6300SRichard Henderson }
1423951c6300SRichard Henderson 
1424474b2e8fSRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1425951c6300SRichard Henderson {
1426474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14273a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14283a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
14293a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1430951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1431951c6300SRichard Henderson     } else {
1432951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1433951c6300SRichard Henderson         tcg_gen_shr_i64(ret, arg1, t0);
1434951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1435951c6300SRichard Henderson     }
1436951c6300SRichard Henderson }
1437951c6300SRichard Henderson 
1438474b2e8fSRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1439951c6300SRichard Henderson {
1440474b2e8fSRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
14413a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14423a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
14433a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1444951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1445951c6300SRichard Henderson     } else {
1446951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1447951c6300SRichard Henderson         tcg_gen_sar_i64(ret, arg1, t0);
1448951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1449951c6300SRichard Henderson     }
1450951c6300SRichard Henderson }
1451951c6300SRichard Henderson 
145242a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1453951c6300SRichard Henderson {
1454951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
145542a268c2SRichard Henderson         tcg_gen_br(l);
1456951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1457d88a117eSRichard Henderson         l->refs++;
14583a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1459951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1460951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
146142a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14623a13c3f3SRichard Henderson         } else {
146342a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
146442a268c2SRichard Henderson                               label_arg(l));
14653a13c3f3SRichard Henderson         }
1466951c6300SRichard Henderson     }
1467951c6300SRichard Henderson }
1468951c6300SRichard Henderson 
146942a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1470951c6300SRichard Henderson {
1471951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
147242a268c2SRichard Henderson         tcg_gen_br(l);
1473951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1474951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
147542a268c2SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, t0, l);
1476951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1477951c6300SRichard Henderson     }
1478951c6300SRichard Henderson }
1479951c6300SRichard Henderson 
1480951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1481951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1482951c6300SRichard Henderson {
1483951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1484951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1485951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1486951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1487951c6300SRichard Henderson     } else {
14883a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1489951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1490951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1491951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1492951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
14933a13c3f3SRichard Henderson         } else {
1494951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
14953a13c3f3SRichard Henderson         }
1496951c6300SRichard Henderson     }
1497951c6300SRichard Henderson }
1498951c6300SRichard Henderson 
1499951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1500951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1501951c6300SRichard Henderson {
1502951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1503951c6300SRichard Henderson     tcg_gen_setcond_i64(cond, ret, arg1, t0);
1504951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1505951c6300SRichard Henderson }
1506951c6300SRichard Henderson 
1507951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1508951c6300SRichard Henderson {
1509b2e3ae94SRichard Henderson     if (arg2 == 0) {
1510b2e3ae94SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1511b2e3ae94SRichard Henderson     } else if (is_power_of_2(arg2)) {
1512b2e3ae94SRichard Henderson         tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1513b2e3ae94SRichard Henderson     } else {
1514951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1515951c6300SRichard Henderson         tcg_gen_mul_i64(ret, arg1, t0);
1516951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1517951c6300SRichard Henderson     }
1518b2e3ae94SRichard Henderson }
1519951c6300SRichard Henderson 
1520951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1521951c6300SRichard Henderson {
1522951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1523951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1524951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1525951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1526951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1527951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1528951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1529951c6300SRichard Henderson     } else {
1530951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1531951c6300SRichard Henderson     }
1532951c6300SRichard Henderson }
1533951c6300SRichard Henderson 
1534951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1535951c6300SRichard Henderson {
1536951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1537951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1538951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1539951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1540951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1541951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1542951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1543951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1544951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1545951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1546951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1547951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1548951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1549951c6300SRichard Henderson     } else {
1550951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1551951c6300SRichard Henderson     }
1552951c6300SRichard Henderson }
1553951c6300SRichard Henderson 
1554951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1555951c6300SRichard Henderson {
1556951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1557951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1558951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1559951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1560951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1561951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1562951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1563951c6300SRichard Henderson     } else {
1564951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1565951c6300SRichard Henderson     }
1566951c6300SRichard Henderson }
1567951c6300SRichard Henderson 
1568951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1569951c6300SRichard Henderson {
1570951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1571951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1572951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1573951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1574951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1575951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1576951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1577951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1578951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1579951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1580951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1581951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1582951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1583951c6300SRichard Henderson     } else {
1584951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1585951c6300SRichard Henderson     }
1586951c6300SRichard Henderson }
1587951c6300SRichard Henderson 
1588951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1589951c6300SRichard Henderson {
15903a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1591951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1592951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15933a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1594951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1595951c6300SRichard Henderson     } else {
1596951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1597951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1598951c6300SRichard Henderson     }
1599951c6300SRichard Henderson }
1600951c6300SRichard Henderson 
1601951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1602951c6300SRichard Henderson {
16033a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1604951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1605951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16063a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1607951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1608951c6300SRichard Henderson     } else {
1609951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1610951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1611951c6300SRichard Henderson     }
1612951c6300SRichard Henderson }
1613951c6300SRichard Henderson 
1614951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1615951c6300SRichard Henderson {
16163a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1617951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1618951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
16193a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1620951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1621951c6300SRichard Henderson     } else {
1622951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1623951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1624951c6300SRichard Henderson     }
1625951c6300SRichard Henderson }
1626951c6300SRichard Henderson 
1627951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1628951c6300SRichard Henderson {
16293a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1630951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1631951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16323a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1633951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1634951c6300SRichard Henderson     } else {
1635951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1636951c6300SRichard Henderson     }
1637951c6300SRichard Henderson }
1638951c6300SRichard Henderson 
1639951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1640951c6300SRichard Henderson {
16413a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1642951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1643951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16443a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1645951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1646951c6300SRichard Henderson     } else {
1647951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1648951c6300SRichard Henderson     }
1649951c6300SRichard Henderson }
1650951c6300SRichard Henderson 
1651951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1652951c6300SRichard Henderson {
16533a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1654951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1655951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16563a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1657951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1658951c6300SRichard Henderson     } else {
1659951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1660951c6300SRichard Henderson     }
1661951c6300SRichard Henderson }
1662951c6300SRichard Henderson 
1663951c6300SRichard Henderson /* Note: we assume the six high bytes are set to zero */
1664951c6300SRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
1665951c6300SRichard Henderson {
16663a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1667951c6300SRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1668951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16693a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
1670951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
1671951c6300SRichard Henderson     } else {
1672951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1673951c6300SRichard Henderson 
1674951c6300SRichard Henderson         tcg_gen_ext8u_i64(t0, arg);
1675951c6300SRichard Henderson         tcg_gen_shli_i64(t0, t0, 8);
1676951c6300SRichard Henderson         tcg_gen_shri_i64(ret, arg, 8);
1677951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t0);
1678951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1679951c6300SRichard Henderson     }
1680951c6300SRichard Henderson }
1681951c6300SRichard Henderson 
1682951c6300SRichard Henderson /* Note: we assume the four high bytes are set to zero */
1683951c6300SRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
1684951c6300SRichard Henderson {
16853a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1686951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1687951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16883a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
1689951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
1690951c6300SRichard Henderson     } else {
1691a686dc71SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1692a686dc71SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1693a686dc71SRichard Henderson         TCGv_i64 t2 = tcg_const_i64(0x00ff00ff);
1694951c6300SRichard Henderson 
1695a686dc71SRichard Henderson                                         /* arg = ....abcd */
1696a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .....abc */
1697a686dc71SRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .....b.d */
1698a686dc71SRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .....a.c */
1699a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = ....b.d. */
1700a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = ....badc */
1701951c6300SRichard Henderson 
1702a686dc71SRichard Henderson         tcg_gen_shli_i64(t1, ret, 48);  /*  t1 = dc...... */
1703a686dc71SRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ......ba */
1704a686dc71SRichard Henderson         tcg_gen_shri_i64(t1, t1, 32);   /*  t1 = ....dc.. */
1705a686dc71SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = ....dcba */
1706951c6300SRichard Henderson 
1707951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1708951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1709a686dc71SRichard Henderson         tcg_temp_free_i64(t2);
1710951c6300SRichard Henderson     }
1711951c6300SRichard Henderson }
1712951c6300SRichard Henderson 
1713951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1714951c6300SRichard Henderson {
17153a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1716951c6300SRichard Henderson         TCGv_i32 t0, t1;
1717951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1718951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1719951c6300SRichard Henderson 
1720951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1721951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1722951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1723951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1724951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1725951c6300SRichard Henderson         tcg_temp_free_i32(t1);
17263a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1727951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
1728951c6300SRichard Henderson     } else {
1729951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1730951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
17319e821eabSRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
1732951c6300SRichard Henderson 
17339e821eabSRichard Henderson                                         /* arg = abcdefgh */
17349e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
17359e821eabSRichard Henderson         tcg_gen_shri_i64(t0, arg, 8);   /*  t0 = .abcdefg */
17369e821eabSRichard Henderson         tcg_gen_and_i64(t1, arg, t2);   /*  t1 = .b.d.f.h */
17379e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = .a.c.e.g */
17389e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);    /*  t1 = b.d.f.h. */
17399e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = badcfehg */
1740951c6300SRichard Henderson 
17419e821eabSRichard Henderson         tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
17429e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 16);  /*  t0 = ..badcfe */
17439e821eabSRichard Henderson         tcg_gen_and_i64(t1, ret, t2);   /*  t1 = ..dc..hg */
17449e821eabSRichard Henderson         tcg_gen_and_i64(t0, t0, t2);    /*  t0 = ..ba..fe */
17459e821eabSRichard Henderson         tcg_gen_shli_i64(t1, t1, 16);   /*  t1 = dc..hg.. */
17469e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = dcbahgfe */
1747951c6300SRichard Henderson 
17489e821eabSRichard Henderson         tcg_gen_shri_i64(t0, ret, 32);  /*  t0 = ....dcba */
17499e821eabSRichard Henderson         tcg_gen_shli_i64(t1, ret, 32);  /*  t1 = hgfe.... */
17509e821eabSRichard Henderson         tcg_gen_or_i64(ret, t0, t1);    /* ret = hgfedcba */
1751951c6300SRichard Henderson 
1752951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1753951c6300SRichard Henderson         tcg_temp_free_i64(t1);
17549e821eabSRichard Henderson         tcg_temp_free_i64(t2);
1755951c6300SRichard Henderson     }
1756951c6300SRichard Henderson }
1757951c6300SRichard Henderson 
1758951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1759951c6300SRichard Henderson {
17603a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17613a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17623a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
17633a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1764951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1765951c6300SRichard Henderson     } else {
1766951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1767951c6300SRichard Henderson     }
1768951c6300SRichard Henderson }
1769951c6300SRichard Henderson 
1770951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1771951c6300SRichard Henderson {
17723a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17733a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17743a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17753a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1776951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1777951c6300SRichard Henderson     } else {
1778951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1779951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1780951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1781951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1782951c6300SRichard Henderson     }
1783951c6300SRichard Henderson }
1784951c6300SRichard Henderson 
1785951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1786951c6300SRichard Henderson {
17873a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17883a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17893a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17903a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1791951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1792951c6300SRichard Henderson     } else {
1793951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1794951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1795951c6300SRichard Henderson     }
1796951c6300SRichard Henderson }
1797951c6300SRichard Henderson 
1798951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1799951c6300SRichard Henderson {
18003a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18013a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18023a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18033a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1804951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1805951c6300SRichard Henderson     } else {
1806951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1807951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1808951c6300SRichard Henderson     }
1809951c6300SRichard Henderson }
1810951c6300SRichard Henderson 
1811951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1812951c6300SRichard Henderson {
18133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18143a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18153a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18163a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1817951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1818951c6300SRichard Henderson     } else {
1819951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1820951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1821951c6300SRichard Henderson     }
1822951c6300SRichard Henderson }
1823951c6300SRichard Henderson 
1824951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1825951c6300SRichard Henderson {
18263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18273a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18283a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18293a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1830951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1831951c6300SRichard Henderson     } else {
1832951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1833951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1834951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1835951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1836951c6300SRichard Henderson     }
1837951c6300SRichard Henderson }
1838951c6300SRichard Henderson 
18390e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18400e28d006SRichard Henderson {
18410e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
18420e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
18430e28d006SRichard Henderson     } else {
18440e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
18450e28d006SRichard Henderson     }
18460e28d006SRichard Henderson }
18470e28d006SRichard Henderson 
18480e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18490e28d006SRichard Henderson {
18500e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18510e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
18520e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18530e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32((uint32_t)arg2 - 32);
18540e28d006SRichard Henderson         tcg_gen_clz_i32(t, TCGV_LOW(arg1), t);
18550e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
18560e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
18570e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18580e28d006SRichard Henderson         tcg_temp_free_i32(t);
18590e28d006SRichard Henderson     } else {
18600e28d006SRichard Henderson         TCGv_i64 t = tcg_const_i64(arg2);
18610e28d006SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t);
18620e28d006SRichard Henderson         tcg_temp_free_i64(t);
18630e28d006SRichard Henderson     }
18640e28d006SRichard Henderson }
18650e28d006SRichard Henderson 
18660e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18670e28d006SRichard Henderson {
18680e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
18690e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
187014e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
187114e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
187214e99210SRichard Henderson 
187314e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
187414e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
187514e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
187614e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
187714e99210SRichard Henderson         } else {
187814e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
187914e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
188014e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
188114e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
188214e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
188314e99210SRichard Henderson         }
188414e99210SRichard Henderson         z = tcg_const_i64(0);
188514e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
188614e99210SRichard Henderson         tcg_temp_free_i64(t);
188714e99210SRichard Henderson         tcg_temp_free_i64(z);
18880e28d006SRichard Henderson     } else {
18890e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
18900e28d006SRichard Henderson     }
18910e28d006SRichard Henderson }
18920e28d006SRichard Henderson 
18930e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18940e28d006SRichard Henderson {
18950e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18960e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
18970e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18980e28d006SRichard Henderson         TCGv_i32 t32 = tcg_const_i32((uint32_t)arg2 - 32);
18990e28d006SRichard Henderson         tcg_gen_ctz_i32(t32, TCGV_HIGH(arg1), t32);
19000e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
19010e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
19020e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
19030e28d006SRichard Henderson         tcg_temp_free_i32(t32);
190414e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
190514e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
190614e99210SRichard Henderson                && arg2 == 64) {
190714e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
190814e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
190914e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
191014e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
191114e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
191214e99210SRichard Henderson         tcg_temp_free_i64(t);
19130e28d006SRichard Henderson     } else {
19140e28d006SRichard Henderson         TCGv_i64 t64 = tcg_const_i64(arg2);
19150e28d006SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t64);
19160e28d006SRichard Henderson         tcg_temp_free_i64(t64);
19170e28d006SRichard Henderson     }
19180e28d006SRichard Henderson }
19190e28d006SRichard Henderson 
1920086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
1921086920c2SRichard Henderson {
1922086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
1923086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1924086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
1925086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
1926086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
1927086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
1928086920c2SRichard Henderson         tcg_temp_free_i64(t);
1929086920c2SRichard Henderson     } else {
1930086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
1931086920c2SRichard Henderson     }
1932086920c2SRichard Henderson }
1933086920c2SRichard Henderson 
1934a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
1935a768e4e9SRichard Henderson {
1936a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
1937a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
1938a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
1939a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1940a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1941a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
1942a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1943a768e4e9SRichard Henderson     } else {
1944a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
1945a768e4e9SRichard Henderson     }
1946a768e4e9SRichard Henderson }
1947a768e4e9SRichard Henderson 
1948951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1949951c6300SRichard Henderson {
1950951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1951951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1952951c6300SRichard Henderson     } else {
1953951c6300SRichard Henderson         TCGv_i64 t0, t1;
1954951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1955951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1956951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1957951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1958951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1959951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1960951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1961951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1962951c6300SRichard Henderson     }
1963951c6300SRichard Henderson }
1964951c6300SRichard Henderson 
196507dada03SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1966951c6300SRichard Henderson {
196707dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
1968951c6300SRichard Henderson     /* some cases can be optimized here */
1969951c6300SRichard Henderson     if (arg2 == 0) {
1970951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1971951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
1972951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1973951c6300SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, t0);
1974951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1975951c6300SRichard Henderson     } else {
1976951c6300SRichard Henderson         TCGv_i64 t0, t1;
1977951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1978951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1979951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
1980951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
1981951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1982951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1983951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1984951c6300SRichard Henderson     }
1985951c6300SRichard Henderson }
1986951c6300SRichard Henderson 
1987951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1988951c6300SRichard Henderson {
1989951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1990951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
1991951c6300SRichard Henderson     } else {
1992951c6300SRichard Henderson         TCGv_i64 t0, t1;
1993951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1994951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1995951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
1996951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1997951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
1998951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1999951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2000951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2001951c6300SRichard Henderson     }
2002951c6300SRichard Henderson }
2003951c6300SRichard Henderson 
200407dada03SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
2005951c6300SRichard Henderson {
200607dada03SRichard Henderson     tcg_debug_assert(arg2 >= 0 && arg2 < 64);
2007951c6300SRichard Henderson     /* some cases can be optimized here */
2008951c6300SRichard Henderson     if (arg2 == 0) {
2009951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
2010951c6300SRichard Henderson     } else {
2011951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
2012951c6300SRichard Henderson     }
2013951c6300SRichard Henderson }
2014951c6300SRichard Henderson 
2015951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
2016951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
2017951c6300SRichard Henderson {
2018951c6300SRichard Henderson     uint64_t mask;
2019951c6300SRichard Henderson     TCGv_i64 t1;
2020951c6300SRichard Henderson 
2021951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
20220d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2023951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2024951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2025951c6300SRichard Henderson 
20260d0d309dSRichard Henderson     if (len == 64) {
2027951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2028951c6300SRichard Henderson         return;
2029951c6300SRichard Henderson     }
2030951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2031951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2032951c6300SRichard Henderson         return;
2033951c6300SRichard Henderson     }
2034951c6300SRichard Henderson 
20353a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2036951c6300SRichard Henderson         if (ofs >= 32) {
2037951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2038951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2039951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2040951c6300SRichard Henderson             return;
2041951c6300SRichard Henderson         }
2042951c6300SRichard Henderson         if (ofs + len <= 32) {
2043951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2044951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2045951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2046951c6300SRichard Henderson             return;
2047951c6300SRichard Henderson         }
20483a13c3f3SRichard Henderson     }
2049951c6300SRichard Henderson 
2050951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2051951c6300SRichard Henderson 
2052b0a60567SRichard Henderson     if (TCG_TARGET_HAS_extract2_i64) {
2053b0a60567SRichard Henderson         if (ofs + len == 64) {
2054b0a60567SRichard Henderson             tcg_gen_shli_i64(t1, arg1, len);
2055b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, t1, arg2, len);
2056b0a60567SRichard Henderson             goto done;
2057b0a60567SRichard Henderson         }
2058b0a60567SRichard Henderson         if (ofs == 0) {
2059b0a60567SRichard Henderson             tcg_gen_extract2_i64(ret, arg1, arg2, len);
2060b0a60567SRichard Henderson             tcg_gen_rotli_i64(ret, ret, len);
2061b0a60567SRichard Henderson             goto done;
2062b0a60567SRichard Henderson         }
2063b0a60567SRichard Henderson     }
2064b0a60567SRichard Henderson 
2065b0a60567SRichard Henderson     mask = (1ull << len) - 1;
2066951c6300SRichard Henderson     if (ofs + len < 64) {
2067951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2068951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2069951c6300SRichard Henderson     } else {
2070951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2071951c6300SRichard Henderson     }
2072951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2073951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2074b0a60567SRichard Henderson  done:
2075951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2076951c6300SRichard Henderson }
2077951c6300SRichard Henderson 
207807cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
207907cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
208007cc68d5SRichard Henderson {
208107cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
208207cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
208307cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
208407cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
208507cc68d5SRichard Henderson 
208607cc68d5SRichard Henderson     if (ofs + len == 64) {
208707cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
208807cc68d5SRichard Henderson     } else if (ofs == 0) {
208907cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
209007cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
209107cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
209207cc68d5SRichard Henderson         TCGv_i64 zero = tcg_const_i64(0);
209307cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
209407cc68d5SRichard Henderson         tcg_temp_free_i64(zero);
209507cc68d5SRichard Henderson     } else {
209607cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
209707cc68d5SRichard Henderson             if (ofs >= 32) {
209807cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
209907cc68d5SRichard Henderson                                       ofs - 32, len);
210007cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
210107cc68d5SRichard Henderson                 return;
210207cc68d5SRichard Henderson             }
210307cc68d5SRichard Henderson             if (ofs + len <= 32) {
210407cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
210507cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
210607cc68d5SRichard Henderson                 return;
210707cc68d5SRichard Henderson             }
210807cc68d5SRichard Henderson         }
210907cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
211007cc68d5SRichard Henderson            which allows ARG to stay live.  */
211107cc68d5SRichard Henderson         switch (len) {
211207cc68d5SRichard Henderson         case 32:
211307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
211407cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
211507cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
211607cc68d5SRichard Henderson                 return;
211707cc68d5SRichard Henderson             }
211807cc68d5SRichard Henderson             break;
211907cc68d5SRichard Henderson         case 16:
212007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
212107cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
212207cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
212307cc68d5SRichard Henderson                 return;
212407cc68d5SRichard Henderson             }
212507cc68d5SRichard Henderson             break;
212607cc68d5SRichard Henderson         case 8:
212707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
212807cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
212907cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
213007cc68d5SRichard Henderson                 return;
213107cc68d5SRichard Henderson             }
213207cc68d5SRichard Henderson             break;
213307cc68d5SRichard Henderson         }
213407cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
213507cc68d5SRichard Henderson         switch (ofs + len) {
213607cc68d5SRichard Henderson         case 32:
213707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
213807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
213907cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
214007cc68d5SRichard Henderson                 return;
214107cc68d5SRichard Henderson             }
214207cc68d5SRichard Henderson             break;
214307cc68d5SRichard Henderson         case 16:
214407cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
214507cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
214607cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
214707cc68d5SRichard Henderson                 return;
214807cc68d5SRichard Henderson             }
214907cc68d5SRichard Henderson             break;
215007cc68d5SRichard Henderson         case 8:
215107cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
215207cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
215307cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
215407cc68d5SRichard Henderson                 return;
215507cc68d5SRichard Henderson             }
215607cc68d5SRichard Henderson             break;
215707cc68d5SRichard Henderson         }
215807cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
215907cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
216007cc68d5SRichard Henderson     }
216107cc68d5SRichard Henderson }
216207cc68d5SRichard Henderson 
21637ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
21647ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
21657ec8bab3SRichard Henderson {
21667ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
21677ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
21687ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
21697ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
21707ec8bab3SRichard Henderson 
21717ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
21727ec8bab3SRichard Henderson     if (ofs + len == 64) {
21737ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
21747ec8bab3SRichard Henderson         return;
21757ec8bab3SRichard Henderson     }
21767ec8bab3SRichard Henderson     if (ofs == 0) {
21777ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
21787ec8bab3SRichard Henderson         return;
21797ec8bab3SRichard Henderson     }
21807ec8bab3SRichard Henderson 
21817ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
21827ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
21837ec8bab3SRichard Henderson         if (ofs >= 32) {
21847ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
21857ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21867ec8bab3SRichard Henderson             return;
21877ec8bab3SRichard Henderson         }
21887ec8bab3SRichard Henderson         if (ofs + len <= 32) {
21897ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
21907ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21917ec8bab3SRichard Henderson             return;
21927ec8bab3SRichard Henderson         }
21937ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
21947ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
21957ec8bab3SRichard Henderson         goto do_shift_and;
21967ec8bab3SRichard Henderson     }
21977ec8bab3SRichard Henderson 
21987ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
21997ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22007ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
22017ec8bab3SRichard Henderson         return;
22027ec8bab3SRichard Henderson     }
22037ec8bab3SRichard Henderson 
22047ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
22057ec8bab3SRichard Henderson     switch (ofs + len) {
22067ec8bab3SRichard Henderson     case 32:
22077ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
22087ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
22097ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22107ec8bab3SRichard Henderson             return;
22117ec8bab3SRichard Henderson         }
22127ec8bab3SRichard Henderson         break;
22137ec8bab3SRichard Henderson     case 16:
22147ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
22157ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
22167ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22177ec8bab3SRichard Henderson             return;
22187ec8bab3SRichard Henderson         }
22197ec8bab3SRichard Henderson         break;
22207ec8bab3SRichard Henderson     case 8:
22217ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
22227ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
22237ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
22247ec8bab3SRichard Henderson             return;
22257ec8bab3SRichard Henderson         }
22267ec8bab3SRichard Henderson         break;
22277ec8bab3SRichard Henderson     }
22287ec8bab3SRichard Henderson 
22297ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
22307ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
22317ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
22327ec8bab3SRichard Henderson     switch (len) {
22337ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
22347ec8bab3SRichard Henderson     do_shift_and:
22357ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
22367ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
22377ec8bab3SRichard Henderson         break;
22387ec8bab3SRichard Henderson     default:
22397ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
22407ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
22417ec8bab3SRichard Henderson         break;
22427ec8bab3SRichard Henderson     }
22437ec8bab3SRichard Henderson }
22447ec8bab3SRichard Henderson 
22457ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
22467ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
22477ec8bab3SRichard Henderson {
22487ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22497ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22507ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22517ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22527ec8bab3SRichard Henderson 
22537ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
22547ec8bab3SRichard Henderson     if (ofs + len == 64) {
22557ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
22567ec8bab3SRichard Henderson         return;
22577ec8bab3SRichard Henderson     }
22587ec8bab3SRichard Henderson     if (ofs == 0) {
22597ec8bab3SRichard Henderson         switch (len) {
22607ec8bab3SRichard Henderson         case 32:
22617ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22627ec8bab3SRichard Henderson             return;
22637ec8bab3SRichard Henderson         case 16:
22647ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22657ec8bab3SRichard Henderson             return;
22667ec8bab3SRichard Henderson         case 8:
22677ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22687ec8bab3SRichard Henderson             return;
22697ec8bab3SRichard Henderson         }
22707ec8bab3SRichard Henderson     }
22717ec8bab3SRichard Henderson 
22727ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22737ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22747ec8bab3SRichard Henderson         if (ofs >= 32) {
22757ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22767ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
22777ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22787ec8bab3SRichard Henderson         } else if (ofs == 0) {
22797ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
22807ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
22817ec8bab3SRichard Henderson             return;
22827ec8bab3SRichard Henderson         } else if (len > 32) {
22837ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
22847ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
22857ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
22867ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
22877ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22887ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
22897ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
22907ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
22917ec8bab3SRichard Henderson             return;
22927ec8bab3SRichard Henderson         } else {
22937ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
22947ec8bab3SRichard Henderson                field sits at the MSB.  */
22957ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
22967ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
22977ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
22987ec8bab3SRichard Henderson         }
22997ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
23007ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
23017ec8bab3SRichard Henderson         return;
23027ec8bab3SRichard Henderson     }
23037ec8bab3SRichard Henderson 
23047ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
23057ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
23067ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
23077ec8bab3SRichard Henderson         return;
23087ec8bab3SRichard Henderson     }
23097ec8bab3SRichard Henderson 
23107ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
23117ec8bab3SRichard Henderson     switch (ofs + len) {
23127ec8bab3SRichard Henderson     case 32:
23137ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23147ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
23157ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23167ec8bab3SRichard Henderson             return;
23177ec8bab3SRichard Henderson         }
23187ec8bab3SRichard Henderson         break;
23197ec8bab3SRichard Henderson     case 16:
23207ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23217ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
23227ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23237ec8bab3SRichard Henderson             return;
23247ec8bab3SRichard Henderson         }
23257ec8bab3SRichard Henderson         break;
23267ec8bab3SRichard Henderson     case 8:
23277ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23287ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
23297ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
23307ec8bab3SRichard Henderson             return;
23317ec8bab3SRichard Henderson         }
23327ec8bab3SRichard Henderson         break;
23337ec8bab3SRichard Henderson     }
23347ec8bab3SRichard Henderson     switch (len) {
23357ec8bab3SRichard Henderson     case 32:
23367ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23377ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23387ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
23397ec8bab3SRichard Henderson             return;
23407ec8bab3SRichard Henderson         }
23417ec8bab3SRichard Henderson         break;
23427ec8bab3SRichard Henderson     case 16:
23437ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23447ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23457ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
23467ec8bab3SRichard Henderson             return;
23477ec8bab3SRichard Henderson         }
23487ec8bab3SRichard Henderson         break;
23497ec8bab3SRichard Henderson     case 8:
23507ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23517ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23527ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
23537ec8bab3SRichard Henderson             return;
23547ec8bab3SRichard Henderson         }
23557ec8bab3SRichard Henderson         break;
23567ec8bab3SRichard Henderson     }
23577ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23587ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
23597ec8bab3SRichard Henderson }
23607ec8bab3SRichard Henderson 
23612089fcc9SDavid Hildenbrand /*
23622089fcc9SDavid Hildenbrand  * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
23632089fcc9SDavid Hildenbrand  * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
23642089fcc9SDavid Hildenbrand  */
23652089fcc9SDavid Hildenbrand void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
23662089fcc9SDavid Hildenbrand                           unsigned int ofs)
23672089fcc9SDavid Hildenbrand {
23682089fcc9SDavid Hildenbrand     tcg_debug_assert(ofs <= 64);
23692089fcc9SDavid Hildenbrand     if (ofs == 0) {
23702089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, al);
23712089fcc9SDavid Hildenbrand     } else if (ofs == 64) {
23722089fcc9SDavid Hildenbrand         tcg_gen_mov_i64(ret, ah);
23732089fcc9SDavid Hildenbrand     } else if (al == ah) {
23742089fcc9SDavid Hildenbrand         tcg_gen_rotri_i64(ret, al, ofs);
2375fce1296fSRichard Henderson     } else if (TCG_TARGET_HAS_extract2_i64) {
2376fce1296fSRichard Henderson         tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
23772089fcc9SDavid Hildenbrand     } else {
23782089fcc9SDavid Hildenbrand         TCGv_i64 t0 = tcg_temp_new_i64();
23792089fcc9SDavid Hildenbrand         tcg_gen_shri_i64(t0, al, ofs);
23802089fcc9SDavid Hildenbrand         tcg_gen_deposit_i64(ret, t0, ah, 64 - ofs, ofs);
23812089fcc9SDavid Hildenbrand         tcg_temp_free_i64(t0);
23822089fcc9SDavid Hildenbrand     }
23832089fcc9SDavid Hildenbrand }
23842089fcc9SDavid Hildenbrand 
2385951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2386951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2387951c6300SRichard Henderson {
238837ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
238937ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
239037ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
239137ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
239237ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2393951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2394951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2395951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2396951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2397951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2398951c6300SRichard Henderson 
2399951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2400951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2401951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2402951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2403951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2404951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2405951c6300SRichard Henderson         } else {
2406951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2407951c6300SRichard Henderson 
2408951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2409951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2410951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2411951c6300SRichard Henderson 
2412951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2413951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2414951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2415951c6300SRichard Henderson         }
2416951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2417951c6300SRichard Henderson         tcg_temp_free_i32(t1);
24183a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2419951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2420951c6300SRichard Henderson     } else {
2421951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2422951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2423951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2424951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2425951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2426951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2427951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2428951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2429951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2430951c6300SRichard Henderson     }
2431951c6300SRichard Henderson }
2432951c6300SRichard Henderson 
2433951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2434951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2435951c6300SRichard Henderson {
2436951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2437951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2438951c6300SRichard Henderson     } else {
2439951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2440951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2441951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2442951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2443951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2444951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2445951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2446951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2447951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2448951c6300SRichard Henderson     }
2449951c6300SRichard Henderson }
2450951c6300SRichard Henderson 
2451951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2452951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2453951c6300SRichard Henderson {
2454951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2455951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2456951c6300SRichard Henderson     } else {
2457951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2458951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2459951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2460951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2461951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2462951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2463951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2464951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2465951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2466951c6300SRichard Henderson     }
2467951c6300SRichard Henderson }
2468951c6300SRichard Henderson 
2469951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2470951c6300SRichard Henderson {
2471951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2472951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2473951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2474951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2475951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2476951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2477951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2478951c6300SRichard Henderson         tcg_temp_free_i64(t);
2479951c6300SRichard Henderson     } else {
2480951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2481951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2482951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2483951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2484951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2485951c6300SRichard Henderson     }
2486951c6300SRichard Henderson }
2487951c6300SRichard Henderson 
2488951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2489951c6300SRichard Henderson {
2490951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2491951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2492951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2493951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2494951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2495951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2496951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2497951c6300SRichard Henderson         tcg_temp_free_i64(t);
2498951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2499951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2500951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2501951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2502951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2503951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2504951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2505951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2506951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2507951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2508951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2509951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2510951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2511951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2512951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2513951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2514951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2515951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2516951c6300SRichard Henderson     } else {
2517951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2518951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2519951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2520951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2521951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2522951c6300SRichard Henderson     }
2523951c6300SRichard Henderson }
2524951c6300SRichard Henderson 
25255087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
25265087abfbSRichard Henderson {
25275087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
25285087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
25295087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
25305087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
25315087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
25325087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
25335087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
25345087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
25355087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
25365087abfbSRichard Henderson     tcg_temp_free_i64(t0);
25375087abfbSRichard Henderson     tcg_temp_free_i64(t1);
25385087abfbSRichard Henderson     tcg_temp_free_i64(t2);
25395087abfbSRichard Henderson }
25405087abfbSRichard Henderson 
2541b87fb8cdSRichard Henderson void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2542b87fb8cdSRichard Henderson {
2543b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
2544b87fb8cdSRichard Henderson }
2545b87fb8cdSRichard Henderson 
2546b87fb8cdSRichard Henderson void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2547b87fb8cdSRichard Henderson {
2548b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
2549b87fb8cdSRichard Henderson }
2550b87fb8cdSRichard Henderson 
2551b87fb8cdSRichard Henderson void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2552b87fb8cdSRichard Henderson {
2553b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
2554b87fb8cdSRichard Henderson }
2555b87fb8cdSRichard Henderson 
2556b87fb8cdSRichard Henderson void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
2557b87fb8cdSRichard Henderson {
2558b87fb8cdSRichard Henderson     tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
2559b87fb8cdSRichard Henderson }
2560b87fb8cdSRichard Henderson 
2561ff1f11f7SRichard Henderson void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
2562ff1f11f7SRichard Henderson {
2563ff1f11f7SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
2564ff1f11f7SRichard Henderson 
2565ff1f11f7SRichard Henderson     tcg_gen_sari_i64(t, a, 63);
2566ff1f11f7SRichard Henderson     tcg_gen_xor_i64(ret, a, t);
2567ff1f11f7SRichard Henderson     tcg_gen_sub_i64(ret, ret, t);
2568ff1f11f7SRichard Henderson     tcg_temp_free_i64(t);
2569ff1f11f7SRichard Henderson }
2570ff1f11f7SRichard Henderson 
2571951c6300SRichard Henderson /* Size changing operations.  */
2572951c6300SRichard Henderson 
2573609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2574951c6300SRichard Henderson {
25753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2576951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2577609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2578b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2579ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2580951c6300SRichard Henderson     } else {
2581dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2582609ad705SRichard Henderson     }
2583609ad705SRichard Henderson }
2584609ad705SRichard Henderson 
2585609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2586609ad705SRichard Henderson {
2587609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2588609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2589609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2590b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2591ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2592951c6300SRichard Henderson     } else {
2593951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2594609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2595dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2596951c6300SRichard Henderson         tcg_temp_free_i64(t);
2597951c6300SRichard Henderson     }
2598951c6300SRichard Henderson }
2599951c6300SRichard Henderson 
2600951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2601951c6300SRichard Henderson {
26023a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2603951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2604951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
26053a13c3f3SRichard Henderson     } else {
2606b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2607ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26083a13c3f3SRichard Henderson     }
2609951c6300SRichard Henderson }
2610951c6300SRichard Henderson 
2611951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2612951c6300SRichard Henderson {
26133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2614951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2615951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
26163a13c3f3SRichard Henderson     } else {
2617b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2618ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
26193a13c3f3SRichard Henderson     }
2620951c6300SRichard Henderson }
2621951c6300SRichard Henderson 
2622951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2623951c6300SRichard Henderson {
26243a13c3f3SRichard Henderson     TCGv_i64 tmp;
26253a13c3f3SRichard Henderson 
26263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2627951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2628951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
26293a13c3f3SRichard Henderson         return;
26303a13c3f3SRichard Henderson     }
26313a13c3f3SRichard Henderson 
26323a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2633951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2634951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2635951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2636951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2637951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2638951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2639951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2640951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2641951c6300SRichard Henderson     } else {
2642951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2643951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2644951c6300SRichard Henderson     }
2645951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2646951c6300SRichard Henderson }
2647951c6300SRichard Henderson 
2648951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2649951c6300SRichard Henderson {
26503a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2651951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2652951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
26533a13c3f3SRichard Henderson     } else {
2654609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2655609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
26563a13c3f3SRichard Henderson     }
2657951c6300SRichard Henderson }
2658951c6300SRichard Henderson 
2659951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2660951c6300SRichard Henderson {
2661951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2662951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2663951c6300SRichard Henderson }
2664951c6300SRichard Henderson 
2665951c6300SRichard Henderson /* QEMU specific operations.  */
2666951c6300SRichard Henderson 
266707ea28b4SRichard Henderson void tcg_gen_exit_tb(TranslationBlock *tb, unsigned idx)
266807ea28b4SRichard Henderson {
266907ea28b4SRichard Henderson     uintptr_t val = (uintptr_t)tb + idx;
267007ea28b4SRichard Henderson 
267107ea28b4SRichard Henderson     if (tb == NULL) {
267207ea28b4SRichard Henderson         tcg_debug_assert(idx == 0);
267307ea28b4SRichard Henderson     } else if (idx <= TB_EXIT_IDXMAX) {
267407ea28b4SRichard Henderson #ifdef CONFIG_DEBUG_TCG
267507ea28b4SRichard Henderson         /* This is an exit following a goto_tb.  Verify that we have
267607ea28b4SRichard Henderson            seen this numbered exit before, via tcg_gen_goto_tb.  */
267707ea28b4SRichard Henderson         tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
267807ea28b4SRichard Henderson #endif
2679d7f425fdSRichard Henderson         /* When not chaining, exit without indicating a link.  */
2680d7f425fdSRichard Henderson         if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
2681d7f425fdSRichard Henderson             val = 0;
2682d7f425fdSRichard Henderson         }
268307ea28b4SRichard Henderson     } else {
268407ea28b4SRichard Henderson         /* This is an exit via the exitreq label.  */
268507ea28b4SRichard Henderson         tcg_debug_assert(idx == TB_EXIT_REQUESTED);
268607ea28b4SRichard Henderson     }
268707ea28b4SRichard Henderson 
2688e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
268907ea28b4SRichard Henderson     tcg_gen_op1i(INDEX_op_exit_tb, val);
269007ea28b4SRichard Henderson }
269107ea28b4SRichard Henderson 
2692951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2693951c6300SRichard Henderson {
2694951c6300SRichard Henderson     /* We only support two chained exits.  */
269507ea28b4SRichard Henderson     tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
2696951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2697951c6300SRichard Henderson     /* Verify that we havn't seen this numbered exit before.  */
2698b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2699b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2700951c6300SRichard Henderson #endif
2701e6d86bedSEmilio G. Cota     plugin_gen_disable_mem_helpers();
2702d7f425fdSRichard Henderson     /* When not chaining, we simply fall through to the "fallback" exit.  */
2703d7f425fdSRichard Henderson     if (!qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
2704951c6300SRichard Henderson         tcg_gen_op1i(INDEX_op_goto_tb, idx);
2705951c6300SRichard Henderson     }
2706d7f425fdSRichard Henderson }
2707951c6300SRichard Henderson 
27087f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2709cedbcb01SEmilio G. Cota {
2710cedbcb01SEmilio G. Cota     if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
2711e6d86bedSEmilio G. Cota         TCGv_ptr ptr;
2712e6d86bedSEmilio G. Cota 
2713e6d86bedSEmilio G. Cota         plugin_gen_disable_mem_helpers();
2714e6d86bedSEmilio G. Cota         ptr = tcg_temp_new_ptr();
27151c2adb95SRichard Henderson         gen_helper_lookup_tb_ptr(ptr, cpu_env);
2716ae8b75dcSRichard Henderson         tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2717cedbcb01SEmilio G. Cota         tcg_temp_free_ptr(ptr);
2718cedbcb01SEmilio G. Cota     } else {
271907ea28b4SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
2720cedbcb01SEmilio G. Cota     }
2721cedbcb01SEmilio G. Cota }
2722cedbcb01SEmilio G. Cota 
272314776ab5STony Nguyen static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
2724951c6300SRichard Henderson {
27251f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
27261f00b27fSSergey Sorokin     (void)get_alignment_bits(op);
27271f00b27fSSergey Sorokin 
2728951c6300SRichard Henderson     switch (op & MO_SIZE) {
2729951c6300SRichard Henderson     case MO_8:
2730951c6300SRichard Henderson         op &= ~MO_BSWAP;
2731951c6300SRichard Henderson         break;
2732951c6300SRichard Henderson     case MO_16:
2733951c6300SRichard Henderson         break;
2734951c6300SRichard Henderson     case MO_32:
2735951c6300SRichard Henderson         if (!is64) {
2736951c6300SRichard Henderson             op &= ~MO_SIGN;
2737951c6300SRichard Henderson         }
2738951c6300SRichard Henderson         break;
2739951c6300SRichard Henderson     case MO_64:
2740951c6300SRichard Henderson         if (!is64) {
2741951c6300SRichard Henderson             tcg_abort();
2742951c6300SRichard Henderson         }
2743951c6300SRichard Henderson         break;
2744951c6300SRichard Henderson     }
2745951c6300SRichard Henderson     if (st) {
2746951c6300SRichard Henderson         op &= ~MO_SIGN;
2747951c6300SRichard Henderson     }
2748951c6300SRichard Henderson     return op;
2749951c6300SRichard Henderson }
2750951c6300SRichard Henderson 
2751c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
275214776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2753951c6300SRichard Henderson {
275459227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2755951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
275659227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2757951c6300SRichard Henderson #else
2758c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
275959227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2760c45cb8bbSRichard Henderson     } else {
2761ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2762c45cb8bbSRichard Henderson     }
2763951c6300SRichard Henderson #endif
2764c45cb8bbSRichard Henderson }
2765c45cb8bbSRichard Henderson 
2766c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
276714776ab5STony Nguyen                          MemOp memop, TCGArg idx)
2768c45cb8bbSRichard Henderson {
276959227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2770c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2771c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
277259227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2773c45cb8bbSRichard Henderson     } else {
2774ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2775c45cb8bbSRichard Henderson     }
2776c45cb8bbSRichard Henderson #else
2777c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
277859227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
277959227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2780c45cb8bbSRichard Henderson     } else {
278159227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2782c45cb8bbSRichard Henderson     }
2783c45cb8bbSRichard Henderson #endif
2784c45cb8bbSRichard Henderson }
2785951c6300SRichard Henderson 
2786b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2787b32dc337SPranith Kumar {
2788b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2789b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2790b32dc337SPranith Kumar #endif
2791b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2792b32dc337SPranith Kumar     if (type) {
2793b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2794b32dc337SPranith Kumar     }
2795b32dc337SPranith Kumar }
2796b32dc337SPranith Kumar 
2797fcc54ab5SAlex Bennée static inline TCGv plugin_prep_mem_callbacks(TCGv vaddr)
2798fcc54ab5SAlex Bennée {
2799fcc54ab5SAlex Bennée #ifdef CONFIG_PLUGIN
2800fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
2801fcc54ab5SAlex Bennée         /* Save a copy of the vaddr for use after a load.  */
2802fcc54ab5SAlex Bennée         TCGv temp = tcg_temp_new();
2803fcc54ab5SAlex Bennée         tcg_gen_mov_tl(temp, vaddr);
2804fcc54ab5SAlex Bennée         return temp;
2805fcc54ab5SAlex Bennée     }
2806fcc54ab5SAlex Bennée #endif
2807fcc54ab5SAlex Bennée     return vaddr;
2808fcc54ab5SAlex Bennée }
2809fcc54ab5SAlex Bennée 
2810e6d86bedSEmilio G. Cota static inline void plugin_gen_mem_callbacks(TCGv vaddr, uint16_t info)
2811e6d86bedSEmilio G. Cota {
2812e6d86bedSEmilio G. Cota #ifdef CONFIG_PLUGIN
2813fcc54ab5SAlex Bennée     if (tcg_ctx->plugin_insn != NULL) {
2814e6d86bedSEmilio G. Cota         plugin_gen_empty_mem_callback(vaddr, info);
2815fcc54ab5SAlex Bennée         tcg_temp_free(vaddr);
2816fcc54ab5SAlex Bennée     }
2817e6d86bedSEmilio G. Cota #endif
2818e6d86bedSEmilio G. Cota }
2819e6d86bedSEmilio G. Cota 
282014776ab5STony Nguyen void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2821951c6300SRichard Henderson {
282214776ab5STony Nguyen     MemOp orig_memop;
2823e6d86bedSEmilio G. Cota     uint16_t info = trace_mem_get_info(memop, idx, 0);
2824e1dcf352SRichard Henderson 
2825b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2826951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2827e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2828e1dcf352SRichard Henderson 
2829e1dcf352SRichard Henderson     orig_memop = memop;
2830e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2831e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2832e1dcf352SRichard Henderson         /* The bswap primitive requires zero-extended input.  */
2833e1dcf352SRichard Henderson         if ((memop & MO_SSIZE) == MO_SW) {
2834e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2835e1dcf352SRichard Henderson         }
2836e1dcf352SRichard Henderson     }
2837e1dcf352SRichard Henderson 
2838fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2839c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
2840e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2841e1dcf352SRichard Henderson 
2842e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2843e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2844e1dcf352SRichard Henderson         case MO_16:
2845e1dcf352SRichard Henderson             tcg_gen_bswap16_i32(val, val);
2846e1dcf352SRichard Henderson             if (orig_memop & MO_SIGN) {
2847e1dcf352SRichard Henderson                 tcg_gen_ext16s_i32(val, val);
2848e1dcf352SRichard Henderson             }
2849e1dcf352SRichard Henderson             break;
2850e1dcf352SRichard Henderson         case MO_32:
2851e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(val, val);
2852e1dcf352SRichard Henderson             break;
2853e1dcf352SRichard Henderson         default:
2854e1dcf352SRichard Henderson             g_assert_not_reached();
2855e1dcf352SRichard Henderson         }
2856e1dcf352SRichard Henderson     }
2857951c6300SRichard Henderson }
2858951c6300SRichard Henderson 
285914776ab5STony Nguyen void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2860951c6300SRichard Henderson {
2861e1dcf352SRichard Henderson     TCGv_i32 swap = NULL;
2862e6d86bedSEmilio G. Cota     uint16_t info = trace_mem_get_info(memop, idx, 1);
2863e1dcf352SRichard Henderson 
2864b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2865951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
2866e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2867e1dcf352SRichard Henderson 
2868e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2869e1dcf352SRichard Henderson         swap = tcg_temp_new_i32();
2870e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
2871e1dcf352SRichard Henderson         case MO_16:
2872e1dcf352SRichard Henderson             tcg_gen_ext16u_i32(swap, val);
2873e1dcf352SRichard Henderson             tcg_gen_bswap16_i32(swap, swap);
2874e1dcf352SRichard Henderson             break;
2875e1dcf352SRichard Henderson         case MO_32:
2876e1dcf352SRichard Henderson             tcg_gen_bswap32_i32(swap, val);
2877e1dcf352SRichard Henderson             break;
2878e1dcf352SRichard Henderson         default:
2879e1dcf352SRichard Henderson             g_assert_not_reached();
2880e1dcf352SRichard Henderson         }
2881e1dcf352SRichard Henderson         val = swap;
2882e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2883e1dcf352SRichard Henderson     }
2884e1dcf352SRichard Henderson 
2885fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2886*07ce0b05SRichard Henderson     if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) {
2887*07ce0b05SRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx);
2888*07ce0b05SRichard Henderson     } else {
2889c45cb8bbSRichard Henderson         gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
2890*07ce0b05SRichard Henderson     }
2891e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2892e1dcf352SRichard Henderson 
2893e1dcf352SRichard Henderson     if (swap) {
2894e1dcf352SRichard Henderson         tcg_temp_free_i32(swap);
2895e1dcf352SRichard Henderson     }
2896951c6300SRichard Henderson }
2897951c6300SRichard Henderson 
289814776ab5STony Nguyen void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
2899951c6300SRichard Henderson {
290014776ab5STony Nguyen     MemOp orig_memop;
2901e6d86bedSEmilio G. Cota     uint16_t info;
2902e1dcf352SRichard Henderson 
29033a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2904951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
2905951c6300SRichard Henderson         if (memop & MO_SIGN) {
2906951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
2907951c6300SRichard Henderson         } else {
2908951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
2909951c6300SRichard Henderson         }
2910951c6300SRichard Henderson         return;
2911951c6300SRichard Henderson     }
2912951c6300SRichard Henderson 
2913e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2914c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2915e6d86bedSEmilio G. Cota     info = trace_mem_get_info(memop, idx, 0);
2916e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2917e1dcf352SRichard Henderson 
2918e1dcf352SRichard Henderson     orig_memop = memop;
2919e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2920e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2921e1dcf352SRichard Henderson         /* The bswap primitive requires zero-extended input.  */
2922e1dcf352SRichard Henderson         if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
2923e1dcf352SRichard Henderson             memop &= ~MO_SIGN;
2924e1dcf352SRichard Henderson         }
2925e1dcf352SRichard Henderson     }
2926e1dcf352SRichard Henderson 
2927fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2928c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
2929e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2930e1dcf352SRichard Henderson 
2931e1dcf352SRichard Henderson     if ((orig_memop ^ memop) & MO_BSWAP) {
2932e1dcf352SRichard Henderson         switch (orig_memop & MO_SIZE) {
2933e1dcf352SRichard Henderson         case MO_16:
2934e1dcf352SRichard Henderson             tcg_gen_bswap16_i64(val, val);
2935e1dcf352SRichard Henderson             if (orig_memop & MO_SIGN) {
2936e1dcf352SRichard Henderson                 tcg_gen_ext16s_i64(val, val);
2937e1dcf352SRichard Henderson             }
2938e1dcf352SRichard Henderson             break;
2939e1dcf352SRichard Henderson         case MO_32:
2940e1dcf352SRichard Henderson             tcg_gen_bswap32_i64(val, val);
2941e1dcf352SRichard Henderson             if (orig_memop & MO_SIGN) {
2942e1dcf352SRichard Henderson                 tcg_gen_ext32s_i64(val, val);
2943e1dcf352SRichard Henderson             }
2944e1dcf352SRichard Henderson             break;
2945e1dcf352SRichard Henderson         case MO_64:
2946e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(val, val);
2947e1dcf352SRichard Henderson             break;
2948e1dcf352SRichard Henderson         default:
2949e1dcf352SRichard Henderson             g_assert_not_reached();
2950e1dcf352SRichard Henderson         }
2951e1dcf352SRichard Henderson     }
2952951c6300SRichard Henderson }
2953951c6300SRichard Henderson 
295414776ab5STony Nguyen void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
2955951c6300SRichard Henderson {
2956e1dcf352SRichard Henderson     TCGv_i64 swap = NULL;
2957e6d86bedSEmilio G. Cota     uint16_t info;
2958e1dcf352SRichard Henderson 
29593a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2960951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
2961951c6300SRichard Henderson         return;
2962951c6300SRichard Henderson     }
2963951c6300SRichard Henderson 
2964e1dcf352SRichard Henderson     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2965c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
2966e6d86bedSEmilio G. Cota     info = trace_mem_get_info(memop, idx, 1);
2967e6d86bedSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
2968e1dcf352SRichard Henderson 
2969e1dcf352SRichard Henderson     if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2970e1dcf352SRichard Henderson         swap = tcg_temp_new_i64();
2971e1dcf352SRichard Henderson         switch (memop & MO_SIZE) {
2972e1dcf352SRichard Henderson         case MO_16:
2973e1dcf352SRichard Henderson             tcg_gen_ext16u_i64(swap, val);
2974e1dcf352SRichard Henderson             tcg_gen_bswap16_i64(swap, swap);
2975e1dcf352SRichard Henderson             break;
2976e1dcf352SRichard Henderson         case MO_32:
2977e1dcf352SRichard Henderson             tcg_gen_ext32u_i64(swap, val);
2978e1dcf352SRichard Henderson             tcg_gen_bswap32_i64(swap, swap);
2979e1dcf352SRichard Henderson             break;
2980e1dcf352SRichard Henderson         case MO_64:
2981e1dcf352SRichard Henderson             tcg_gen_bswap64_i64(swap, val);
2982e1dcf352SRichard Henderson             break;
2983e1dcf352SRichard Henderson         default:
2984e1dcf352SRichard Henderson             g_assert_not_reached();
2985e1dcf352SRichard Henderson         }
2986e1dcf352SRichard Henderson         val = swap;
2987e1dcf352SRichard Henderson         memop &= ~MO_BSWAP;
2988e1dcf352SRichard Henderson     }
2989e1dcf352SRichard Henderson 
2990fcc54ab5SAlex Bennée     addr = plugin_prep_mem_callbacks(addr);
2991c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
2992e6d86bedSEmilio G. Cota     plugin_gen_mem_callbacks(addr, info);
2993e1dcf352SRichard Henderson 
2994e1dcf352SRichard Henderson     if (swap) {
2995e1dcf352SRichard Henderson         tcg_temp_free_i64(swap);
2996e1dcf352SRichard Henderson     }
2997951c6300SRichard Henderson }
2998c482cb11SRichard Henderson 
299914776ab5STony Nguyen static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
3000c482cb11SRichard Henderson {
3001c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3002c482cb11SRichard Henderson     case MO_SB:
3003c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
3004c482cb11SRichard Henderson         break;
3005c482cb11SRichard Henderson     case MO_UB:
3006c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
3007c482cb11SRichard Henderson         break;
3008c482cb11SRichard Henderson     case MO_SW:
3009c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
3010c482cb11SRichard Henderson         break;
3011c482cb11SRichard Henderson     case MO_UW:
3012c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
3013c482cb11SRichard Henderson         break;
3014c482cb11SRichard Henderson     default:
3015c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
3016c482cb11SRichard Henderson         break;
3017c482cb11SRichard Henderson     }
3018c482cb11SRichard Henderson }
3019c482cb11SRichard Henderson 
302014776ab5STony Nguyen static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
3021c482cb11SRichard Henderson {
3022c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
3023c482cb11SRichard Henderson     case MO_SB:
3024c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
3025c482cb11SRichard Henderson         break;
3026c482cb11SRichard Henderson     case MO_UB:
3027c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
3028c482cb11SRichard Henderson         break;
3029c482cb11SRichard Henderson     case MO_SW:
3030c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
3031c482cb11SRichard Henderson         break;
3032c482cb11SRichard Henderson     case MO_UW:
3033c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
3034c482cb11SRichard Henderson         break;
3035c482cb11SRichard Henderson     case MO_SL:
3036c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
3037c482cb11SRichard Henderson         break;
3038c482cb11SRichard Henderson     case MO_UL:
3039c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
3040c482cb11SRichard Henderson         break;
3041c482cb11SRichard Henderson     default:
3042c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
3043c482cb11SRichard Henderson         break;
3044c482cb11SRichard Henderson     }
3045c482cb11SRichard Henderson }
3046c482cb11SRichard Henderson 
3047c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
3048c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
3049c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
3050c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
3051c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
3052c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
3053c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
3054c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
3055c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
3056c482cb11SRichard Henderson #else
3057c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
3058c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
3059c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
3060c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
3061c482cb11SRichard Henderson #endif
3062c482cb11SRichard Henderson 
3063df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3064df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
3065df79b996SRichard Henderson #else
3066df79b996SRichard Henderson # define WITH_ATOMIC64(X)
3067df79b996SRichard Henderson #endif
3068df79b996SRichard Henderson 
3069c482cb11SRichard Henderson static void * const table_cmpxchg[16] = {
3070c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
3071c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
3072c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
3073c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
3074c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
3075df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
3076df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
3077c482cb11SRichard Henderson };
3078c482cb11SRichard Henderson 
3079c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
308014776ab5STony Nguyen                                 TCGv_i32 newv, TCGArg idx, MemOp memop)
3081c482cb11SRichard Henderson {
3082c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3083c482cb11SRichard Henderson 
3084b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
3085c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
3086c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
3087c482cb11SRichard Henderson 
3088c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
3089c482cb11SRichard Henderson 
3090c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
3091c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
3092c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3093c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
3094c482cb11SRichard Henderson 
3095c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3096c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
3097c482cb11SRichard Henderson         } else {
3098c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
3099c482cb11SRichard Henderson         }
3100c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
3101c482cb11SRichard Henderson     } else {
3102c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
3103c482cb11SRichard Henderson 
3104c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3105c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3106c482cb11SRichard Henderson 
3107c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
3108c482cb11SRichard Henderson         {
3109c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
31101c2adb95SRichard Henderson             gen(retv, cpu_env, addr, cmpv, newv, oi);
3111c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
3112c482cb11SRichard Henderson         }
3113c482cb11SRichard Henderson #else
31141c2adb95SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv);
3115c482cb11SRichard Henderson #endif
3116c482cb11SRichard Henderson 
3117c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3118c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
3119c482cb11SRichard Henderson         }
3120c482cb11SRichard Henderson     }
3121c482cb11SRichard Henderson }
3122c482cb11SRichard Henderson 
3123c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
312414776ab5STony Nguyen                                 TCGv_i64 newv, TCGArg idx, MemOp memop)
3125c482cb11SRichard Henderson {
3126c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3127c482cb11SRichard Henderson 
3128b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
3129c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
3130c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
3131c482cb11SRichard Henderson 
3132c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
3133c482cb11SRichard Henderson 
3134c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
3135c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
3136c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3137c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
3138c482cb11SRichard Henderson 
3139c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3140c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
3141c482cb11SRichard Henderson         } else {
3142c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
3143c482cb11SRichard Henderson         }
3144c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
3145c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
3146df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3147c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
3148c482cb11SRichard Henderson 
3149c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
3150c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3151c482cb11SRichard Henderson 
3152c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
3153c482cb11SRichard Henderson         {
3154c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
31551c2adb95SRichard Henderson             gen(retv, cpu_env, addr, cmpv, newv, oi);
3156c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
3157c482cb11SRichard Henderson         }
3158c482cb11SRichard Henderson #else
31591c2adb95SRichard Henderson         gen(retv, cpu_env, addr, cmpv, newv);
3160c482cb11SRichard Henderson #endif
3161df79b996SRichard Henderson #else
31621c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
316379b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
316479b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
316579b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
3166df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3167c482cb11SRichard Henderson     } else {
3168c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
3169c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
3170c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3171c482cb11SRichard Henderson 
3172c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
3173c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
3174c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
3175c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
3176c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
3177c482cb11SRichard Henderson 
3178c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
3179c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3180c482cb11SRichard Henderson 
3181c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3182c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
3183c482cb11SRichard Henderson         }
3184c482cb11SRichard Henderson     }
3185c482cb11SRichard Henderson }
3186c482cb11SRichard Henderson 
3187c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
318814776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3189c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
3190c482cb11SRichard Henderson {
3191c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
3192c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
3193c482cb11SRichard Henderson 
3194c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3195c482cb11SRichard Henderson 
3196852f933eSRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop);
3197852f933eSRichard Henderson     tcg_gen_ext_i32(t2, val, memop);
3198852f933eSRichard Henderson     gen(t2, t1, t2);
3199c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
3200c482cb11SRichard Henderson 
3201c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
3202c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
3203c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
3204c482cb11SRichard Henderson }
3205c482cb11SRichard Henderson 
3206c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
320714776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3208c482cb11SRichard Henderson {
3209c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
3210c482cb11SRichard Henderson 
3211c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
3212c482cb11SRichard Henderson 
3213c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
3214c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
3215c482cb11SRichard Henderson 
3216c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
3217c482cb11SRichard Henderson     {
3218c482cb11SRichard Henderson         TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
32191c2adb95SRichard Henderson         gen(ret, cpu_env, addr, val, oi);
3220c482cb11SRichard Henderson         tcg_temp_free_i32(oi);
3221c482cb11SRichard Henderson     }
3222c482cb11SRichard Henderson #else
32231c2adb95SRichard Henderson     gen(ret, cpu_env, addr, val);
3224c482cb11SRichard Henderson #endif
3225c482cb11SRichard Henderson 
3226c482cb11SRichard Henderson     if (memop & MO_SIGN) {
3227c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
3228c482cb11SRichard Henderson     }
3229c482cb11SRichard Henderson }
3230c482cb11SRichard Henderson 
3231c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
323214776ab5STony Nguyen                                 TCGArg idx, MemOp memop, bool new_val,
3233c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
3234c482cb11SRichard Henderson {
3235c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3236c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3237c482cb11SRichard Henderson 
3238c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3239c482cb11SRichard Henderson 
3240852f933eSRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop);
3241852f933eSRichard Henderson     tcg_gen_ext_i64(t2, val, memop);
3242852f933eSRichard Henderson     gen(t2, t1, t2);
3243c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
3244c482cb11SRichard Henderson 
3245c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
3246c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
3247c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
3248c482cb11SRichard Henderson }
3249c482cb11SRichard Henderson 
3250c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
325114776ab5STony Nguyen                              TCGArg idx, MemOp memop, void * const table[])
3252c482cb11SRichard Henderson {
3253c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
3254c482cb11SRichard Henderson 
3255c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
3256df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
3257c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
3258c482cb11SRichard Henderson 
3259c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
3260c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
3261c482cb11SRichard Henderson 
3262c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
3263c482cb11SRichard Henderson         {
3264c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
32651c2adb95SRichard Henderson             gen(ret, cpu_env, addr, val, oi);
3266c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
3267c482cb11SRichard Henderson         }
3268c482cb11SRichard Henderson #else
32691c2adb95SRichard Henderson         gen(ret, cpu_env, addr, val);
3270c482cb11SRichard Henderson #endif
3271df79b996SRichard Henderson #else
32721c2adb95SRichard Henderson         gen_helper_exit_atomic(cpu_env);
327379b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
327479b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
327579b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
3276df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3277c482cb11SRichard Henderson     } else {
3278c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
3279c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3280c482cb11SRichard Henderson 
3281c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
3282c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
3283c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
3284c482cb11SRichard Henderson 
3285c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
3286c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3287c482cb11SRichard Henderson 
3288c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3289c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
3290c482cb11SRichard Henderson         }
3291c482cb11SRichard Henderson     }
3292c482cb11SRichard Henderson }
3293c482cb11SRichard Henderson 
3294c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
3295c482cb11SRichard Henderson static void * const table_##NAME[16] = {                                \
3296c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
3297c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
3298c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
3299c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
3300c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
3301df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
3302df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3303c482cb11SRichard Henderson };                                                                      \
3304c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
330514776ab5STony Nguyen     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop)    \
3306c482cb11SRichard Henderson {                                                                       \
3307b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3308c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3309c482cb11SRichard Henderson     } else {                                                            \
3310c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3311c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3312c482cb11SRichard Henderson     }                                                                   \
3313c482cb11SRichard Henderson }                                                                       \
3314c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
331514776ab5STony Nguyen     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop)    \
3316c482cb11SRichard Henderson {                                                                       \
3317b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3318c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3319c482cb11SRichard Henderson     } else {                                                            \
3320c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3321c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3322c482cb11SRichard Henderson     }                                                                   \
3323c482cb11SRichard Henderson }
3324c482cb11SRichard Henderson 
3325c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3326c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3327c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3328c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
33295507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smin, smin, 0)
33305507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umin, umin, 0)
33315507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_smax, smax, 0)
33325507c2bfSRichard Henderson GEN_ATOMIC_HELPER(fetch_umax, umax, 0)
3333c482cb11SRichard Henderson 
3334c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3335c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3336c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3337c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
33385507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smin_fetch, smin, 1)
33395507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umin_fetch, umin, 1)
33405507c2bfSRichard Henderson GEN_ATOMIC_HELPER(smax_fetch, smax, 1)
33415507c2bfSRichard Henderson GEN_ATOMIC_HELPER(umax_fetch, umax, 1)
3342c482cb11SRichard Henderson 
3343c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3344c482cb11SRichard Henderson {
3345c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3346c482cb11SRichard Henderson }
3347c482cb11SRichard Henderson 
3348c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3349c482cb11SRichard Henderson {
3350c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3351c482cb11SRichard Henderson }
3352c482cb11SRichard Henderson 
3353c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3354c482cb11SRichard Henderson 
3355c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3356