xref: /openbmc/qemu/tcg/tcg-op.c (revision b1311c4a)
1951c6300SRichard Henderson /*
2951c6300SRichard Henderson  * Tiny Code Generator for QEMU
3951c6300SRichard Henderson  *
4951c6300SRichard Henderson  * Copyright (c) 2008 Fabrice Bellard
5951c6300SRichard Henderson  *
6951c6300SRichard Henderson  * Permission is hereby granted, free of charge, to any person obtaining a copy
7951c6300SRichard Henderson  * of this software and associated documentation files (the "Software"), to deal
8951c6300SRichard Henderson  * in the Software without restriction, including without limitation the rights
9951c6300SRichard Henderson  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10951c6300SRichard Henderson  * copies of the Software, and to permit persons to whom the Software is
11951c6300SRichard Henderson  * furnished to do so, subject to the following conditions:
12951c6300SRichard Henderson  *
13951c6300SRichard Henderson  * The above copyright notice and this permission notice shall be included in
14951c6300SRichard Henderson  * all copies or substantial portions of the Software.
15951c6300SRichard Henderson  *
16951c6300SRichard Henderson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17951c6300SRichard Henderson  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18951c6300SRichard Henderson  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19951c6300SRichard Henderson  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20951c6300SRichard Henderson  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21951c6300SRichard Henderson  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22951c6300SRichard Henderson  * THE SOFTWARE.
23951c6300SRichard Henderson  */
24951c6300SRichard Henderson 
25757e725bSPeter Maydell #include "qemu/osdep.h"
2633c11879SPaolo Bonzini #include "qemu-common.h"
2733c11879SPaolo Bonzini #include "cpu.h"
2863c91552SPaolo Bonzini #include "exec/exec-all.h"
29951c6300SRichard Henderson #include "tcg.h"
30951c6300SRichard Henderson #include "tcg-op.h"
31b32dc337SPranith Kumar #include "tcg-mo.h"
32dcdaadb6SLluís Vilanova #include "trace-tcg.h"
33dcdaadb6SLluís Vilanova #include "trace/mem.h"
34951c6300SRichard Henderson 
353a13c3f3SRichard Henderson /* Reduce the number of ifdefs below.  This assumes that all uses of
363a13c3f3SRichard Henderson    TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
373a13c3f3SRichard Henderson    the compiler can eliminate.  */
383a13c3f3SRichard Henderson #if TCG_TARGET_REG_BITS == 64
393a13c3f3SRichard Henderson extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
403a13c3f3SRichard Henderson extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
413a13c3f3SRichard Henderson #define TCGV_LOW  TCGV_LOW_link_error
423a13c3f3SRichard Henderson #define TCGV_HIGH TCGV_HIGH_link_error
433a13c3f3SRichard Henderson #endif
44951c6300SRichard Henderson 
45c45cb8bbSRichard Henderson /* Note that this is optimized for sequential allocation during translate.
46c45cb8bbSRichard Henderson    Up to and including filling in the forward link immediately.  We'll do
47c45cb8bbSRichard Henderson    proper termination of the end of the list after we finish translation.  */
48c45cb8bbSRichard Henderson 
49b7e8b17aSRichard Henderson static inline TCGOp *tcg_emit_op(TCGOpcode opc)
50c45cb8bbSRichard Henderson {
51*b1311c4aSEmilio G. Cota     TCGContext *ctx = tcg_ctx;
52c45cb8bbSRichard Henderson     int oi = ctx->gen_next_op_idx;
53c45cb8bbSRichard Henderson     int ni = oi + 1;
54c45cb8bbSRichard Henderson     int pi = oi - 1;
5575e8b9b7SRichard Henderson     TCGOp *op = &ctx->gen_op_buf[oi];
56c45cb8bbSRichard Henderson 
57c45cb8bbSRichard Henderson     tcg_debug_assert(oi < OPC_BUF_SIZE);
58dcb8e758SRichard Henderson     ctx->gen_op_buf[0].prev = oi;
59c45cb8bbSRichard Henderson     ctx->gen_next_op_idx = ni;
60c45cb8bbSRichard Henderson 
6175e8b9b7SRichard Henderson     memset(op, 0, offsetof(TCGOp, args));
6275e8b9b7SRichard Henderson     op->opc = opc;
6375e8b9b7SRichard Henderson     op->prev = pi;
6475e8b9b7SRichard Henderson     op->next = ni;
6575e8b9b7SRichard Henderson 
6675e8b9b7SRichard Henderson     return op;
67c45cb8bbSRichard Henderson }
68c45cb8bbSRichard Henderson 
69b7e8b17aSRichard Henderson void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
70951c6300SRichard Henderson {
71b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
7275e8b9b7SRichard Henderson     op->args[0] = a1;
73951c6300SRichard Henderson }
74951c6300SRichard Henderson 
75b7e8b17aSRichard Henderson void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
76951c6300SRichard Henderson {
77b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
7875e8b9b7SRichard Henderson     op->args[0] = a1;
7975e8b9b7SRichard Henderson     op->args[1] = a2;
80951c6300SRichard Henderson }
81951c6300SRichard Henderson 
82b7e8b17aSRichard Henderson void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
83951c6300SRichard Henderson {
84b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
8575e8b9b7SRichard Henderson     op->args[0] = a1;
8675e8b9b7SRichard Henderson     op->args[1] = a2;
8775e8b9b7SRichard Henderson     op->args[2] = a3;
88951c6300SRichard Henderson }
89951c6300SRichard Henderson 
90b7e8b17aSRichard Henderson void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
91951c6300SRichard Henderson {
92b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
9375e8b9b7SRichard Henderson     op->args[0] = a1;
9475e8b9b7SRichard Henderson     op->args[1] = a2;
9575e8b9b7SRichard Henderson     op->args[2] = a3;
9675e8b9b7SRichard Henderson     op->args[3] = a4;
97951c6300SRichard Henderson }
98951c6300SRichard Henderson 
99b7e8b17aSRichard Henderson void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
100b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5)
101951c6300SRichard Henderson {
102b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
10375e8b9b7SRichard Henderson     op->args[0] = a1;
10475e8b9b7SRichard Henderson     op->args[1] = a2;
10575e8b9b7SRichard Henderson     op->args[2] = a3;
10675e8b9b7SRichard Henderson     op->args[3] = a4;
10775e8b9b7SRichard Henderson     op->args[4] = a5;
108951c6300SRichard Henderson }
109951c6300SRichard Henderson 
110b7e8b17aSRichard Henderson void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
111b7e8b17aSRichard Henderson                  TCGArg a4, TCGArg a5, TCGArg a6)
112951c6300SRichard Henderson {
113b7e8b17aSRichard Henderson     TCGOp *op = tcg_emit_op(opc);
11475e8b9b7SRichard Henderson     op->args[0] = a1;
11575e8b9b7SRichard Henderson     op->args[1] = a2;
11675e8b9b7SRichard Henderson     op->args[2] = a3;
11775e8b9b7SRichard Henderson     op->args[3] = a4;
11875e8b9b7SRichard Henderson     op->args[4] = a5;
11975e8b9b7SRichard Henderson     op->args[5] = a6;
120951c6300SRichard Henderson }
121951c6300SRichard Henderson 
122f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
123f65e19bcSPranith Kumar {
124*b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {
125b7e8b17aSRichard Henderson         tcg_gen_op1(INDEX_op_mb, mb_type);
126f65e19bcSPranith Kumar     }
127f65e19bcSPranith Kumar }
128f65e19bcSPranith Kumar 
129951c6300SRichard Henderson /* 32 bit ops */
130951c6300SRichard Henderson 
131951c6300SRichard Henderson void tcg_gen_addi_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_add_i32(ret, arg1, t0);
139951c6300SRichard Henderson         tcg_temp_free_i32(t0);
140951c6300SRichard Henderson     }
141951c6300SRichard Henderson }
142951c6300SRichard Henderson 
143951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
144951c6300SRichard Henderson {
145951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
146951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
147951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
148951c6300SRichard Henderson     } else {
149951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg1);
150951c6300SRichard Henderson         tcg_gen_sub_i32(ret, t0, arg2);
151951c6300SRichard Henderson         tcg_temp_free_i32(t0);
152951c6300SRichard Henderson     }
153951c6300SRichard Henderson }
154951c6300SRichard Henderson 
155951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
156951c6300SRichard Henderson {
157951c6300SRichard Henderson     /* some cases can be optimized here */
158951c6300SRichard Henderson     if (arg2 == 0) {
159951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
160951c6300SRichard Henderson     } else {
161951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
162951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
163951c6300SRichard Henderson         tcg_temp_free_i32(t0);
164951c6300SRichard Henderson     }
165951c6300SRichard Henderson }
166951c6300SRichard Henderson 
167951c6300SRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
168951c6300SRichard Henderson {
169951c6300SRichard Henderson     TCGv_i32 t0;
170951c6300SRichard Henderson     /* Some cases can be optimized here.  */
171951c6300SRichard Henderson     switch (arg2) {
172951c6300SRichard Henderson     case 0:
173951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
174951c6300SRichard Henderson         return;
175951c6300SRichard Henderson     case 0xffffffffu:
176951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
177951c6300SRichard Henderson         return;
178951c6300SRichard Henderson     case 0xffu:
179951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
180951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
181951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
182951c6300SRichard Henderson             return;
183951c6300SRichard Henderson         }
184951c6300SRichard Henderson         break;
185951c6300SRichard Henderson     case 0xffffu:
186951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
187951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
188951c6300SRichard Henderson             return;
189951c6300SRichard Henderson         }
190951c6300SRichard Henderson         break;
191951c6300SRichard Henderson     }
192951c6300SRichard Henderson     t0 = tcg_const_i32(arg2);
193951c6300SRichard Henderson     tcg_gen_and_i32(ret, arg1, t0);
194951c6300SRichard Henderson     tcg_temp_free_i32(t0);
195951c6300SRichard Henderson }
196951c6300SRichard Henderson 
197951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
198951c6300SRichard Henderson {
199951c6300SRichard Henderson     /* Some cases can be optimized here.  */
200951c6300SRichard Henderson     if (arg2 == -1) {
201951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
202951c6300SRichard Henderson     } else if (arg2 == 0) {
203951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
204951c6300SRichard Henderson     } else {
205951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
206951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
207951c6300SRichard Henderson         tcg_temp_free_i32(t0);
208951c6300SRichard Henderson     }
209951c6300SRichard Henderson }
210951c6300SRichard Henderson 
211951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
212951c6300SRichard Henderson {
213951c6300SRichard Henderson     /* Some cases can be optimized here.  */
214951c6300SRichard Henderson     if (arg2 == 0) {
215951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
216951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
217951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
218951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
219951c6300SRichard Henderson     } else {
220951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
221951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, t0);
222951c6300SRichard Henderson         tcg_temp_free_i32(t0);
223951c6300SRichard Henderson     }
224951c6300SRichard Henderson }
225951c6300SRichard Henderson 
226951c6300SRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
227951c6300SRichard Henderson {
228951c6300SRichard Henderson     tcg_debug_assert(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_shl_i32(ret, arg1, t0);
234951c6300SRichard Henderson         tcg_temp_free_i32(t0);
235951c6300SRichard Henderson     }
236951c6300SRichard Henderson }
237951c6300SRichard Henderson 
238951c6300SRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
239951c6300SRichard Henderson {
240951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
241951c6300SRichard Henderson     if (arg2 == 0) {
242951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
243951c6300SRichard Henderson     } else {
244951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
245951c6300SRichard Henderson         tcg_gen_shr_i32(ret, arg1, t0);
246951c6300SRichard Henderson         tcg_temp_free_i32(t0);
247951c6300SRichard Henderson     }
248951c6300SRichard Henderson }
249951c6300SRichard Henderson 
250951c6300SRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
251951c6300SRichard Henderson {
252951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
253951c6300SRichard Henderson     if (arg2 == 0) {
254951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
255951c6300SRichard Henderson     } else {
256951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
257951c6300SRichard Henderson         tcg_gen_sar_i32(ret, arg1, t0);
258951c6300SRichard Henderson         tcg_temp_free_i32(t0);
259951c6300SRichard Henderson     }
260951c6300SRichard Henderson }
261951c6300SRichard Henderson 
26242a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
263951c6300SRichard Henderson {
264951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
26542a268c2SRichard Henderson         tcg_gen_br(l);
266951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
26742a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
268951c6300SRichard Henderson     }
269951c6300SRichard Henderson }
270951c6300SRichard Henderson 
27142a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
272951c6300SRichard Henderson {
27337ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
27437ed3bf1SRichard Henderson         tcg_gen_br(l);
27537ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
276951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
27742a268c2SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, t0, l);
278951c6300SRichard Henderson         tcg_temp_free_i32(t0);
279951c6300SRichard Henderson     }
28037ed3bf1SRichard Henderson }
281951c6300SRichard Henderson 
282951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
283951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
284951c6300SRichard Henderson {
285951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
286951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
287951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
288951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
289951c6300SRichard Henderson     } else {
290951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
291951c6300SRichard Henderson     }
292951c6300SRichard Henderson }
293951c6300SRichard Henderson 
294951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
295951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
296951c6300SRichard Henderson {
297951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
298951c6300SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, t0);
299951c6300SRichard Henderson     tcg_temp_free_i32(t0);
300951c6300SRichard Henderson }
301951c6300SRichard Henderson 
302951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
303951c6300SRichard Henderson {
304951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
305951c6300SRichard Henderson     tcg_gen_mul_i32(ret, arg1, t0);
306951c6300SRichard Henderson     tcg_temp_free_i32(t0);
307951c6300SRichard Henderson }
308951c6300SRichard Henderson 
309951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
310951c6300SRichard Henderson {
311951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
312951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
313951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
314951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
315951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
316951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
317951c6300SRichard Henderson         tcg_temp_free_i32(t0);
318951c6300SRichard Henderson     } else {
319951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
320951c6300SRichard Henderson     }
321951c6300SRichard Henderson }
322951c6300SRichard Henderson 
323951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
324951c6300SRichard Henderson {
325951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
326951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
327951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
328951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
329951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
330951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
331951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
332951c6300SRichard Henderson         tcg_temp_free_i32(t0);
333951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
334951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
335951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
336951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
337951c6300SRichard Henderson         tcg_temp_free_i32(t0);
338951c6300SRichard Henderson     } else {
339951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
340951c6300SRichard Henderson     }
341951c6300SRichard Henderson }
342951c6300SRichard Henderson 
343951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
344951c6300SRichard Henderson {
345951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
346951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
347951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
348951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
349951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
350951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
351951c6300SRichard Henderson         tcg_temp_free_i32(t0);
352951c6300SRichard Henderson     } else {
353951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
354951c6300SRichard Henderson     }
355951c6300SRichard Henderson }
356951c6300SRichard Henderson 
357951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
358951c6300SRichard Henderson {
359951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
360951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
361951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
362951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
363951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
364951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
365951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
366951c6300SRichard Henderson         tcg_temp_free_i32(t0);
367951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
368951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
369951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
370951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
371951c6300SRichard Henderson         tcg_temp_free_i32(t0);
372951c6300SRichard Henderson     } else {
373951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
374951c6300SRichard Henderson     }
375951c6300SRichard Henderson }
376951c6300SRichard Henderson 
377951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
378951c6300SRichard Henderson {
379951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
380951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
381951c6300SRichard Henderson     } else {
382951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
383951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
384951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
385951c6300SRichard Henderson         tcg_temp_free_i32(t0);
386951c6300SRichard Henderson     }
387951c6300SRichard Henderson }
388951c6300SRichard Henderson 
389951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
390951c6300SRichard Henderson {
391951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
392951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
393951c6300SRichard Henderson     } else {
394951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
395951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
396951c6300SRichard Henderson     }
397951c6300SRichard Henderson }
398951c6300SRichard Henderson 
399951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
400951c6300SRichard Henderson {
401951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
402951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
403951c6300SRichard Henderson     } else {
404951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
405951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
406951c6300SRichard Henderson     }
407951c6300SRichard Henderson }
408951c6300SRichard Henderson 
409951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
410951c6300SRichard Henderson {
411951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
412951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
413951c6300SRichard Henderson     } else {
414951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
415951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
416951c6300SRichard Henderson     }
417951c6300SRichard Henderson }
418951c6300SRichard Henderson 
419951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
420951c6300SRichard Henderson {
421951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
422951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
423951c6300SRichard Henderson     } else {
424951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
425951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
426951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
427951c6300SRichard Henderson         tcg_temp_free_i32(t0);
428951c6300SRichard Henderson     }
429951c6300SRichard Henderson }
430951c6300SRichard Henderson 
4310e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4320e28d006SRichard Henderson {
4330e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4340e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
4350e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
4360e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4370e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4380e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4390e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4400e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4410e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4420e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4430e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4440e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4450e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4460e28d006SRichard Henderson     } else {
4470e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4480e28d006SRichard Henderson     }
4490e28d006SRichard Henderson }
4500e28d006SRichard Henderson 
4510e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4520e28d006SRichard Henderson {
4530e28d006SRichard Henderson     TCGv_i32 t = tcg_const_i32(arg2);
4540e28d006SRichard Henderson     tcg_gen_clz_i32(ret, arg1, t);
4550e28d006SRichard Henderson     tcg_temp_free_i32(t);
4560e28d006SRichard Henderson }
4570e28d006SRichard Henderson 
4580e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4590e28d006SRichard Henderson {
4600e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4610e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4620e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4630e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4640e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4650e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4660e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4670e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4680e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4690e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4700e28d006SRichard Henderson         tcg_temp_free_i64(t2);
47114e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
47214e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
47314e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
47414e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
47514e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
47614e99210SRichard Henderson 
47714e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
47814e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
47914e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
48014e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
48114e99210SRichard Henderson         } else {
48214e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
48314e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
48414e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
48514e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
48614e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
48714e99210SRichard Henderson         }
48814e99210SRichard Henderson         z = tcg_const_i32(0);
48914e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
49014e99210SRichard Henderson         tcg_temp_free_i32(t);
49114e99210SRichard Henderson         tcg_temp_free_i32(z);
4920e28d006SRichard Henderson     } else {
4930e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
4940e28d006SRichard Henderson     }
4950e28d006SRichard Henderson }
4960e28d006SRichard Henderson 
4970e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4980e28d006SRichard Henderson {
49914e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
50014e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
50114e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
50214e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
50314e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
50414e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
50514e99210SRichard Henderson         tcg_temp_free_i32(t);
50614e99210SRichard Henderson     } else {
5070e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32(arg2);
5080e28d006SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, t);
5090e28d006SRichard Henderson         tcg_temp_free_i32(t);
5100e28d006SRichard Henderson     }
51114e99210SRichard Henderson }
5120e28d006SRichard Henderson 
513086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
514086920c2SRichard Henderson {
515086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
516086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
517086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
518086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
519086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
520086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
521086920c2SRichard Henderson         tcg_temp_free_i32(t);
522086920c2SRichard Henderson     } else {
523086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
524086920c2SRichard Henderson     }
525086920c2SRichard Henderson }
526086920c2SRichard Henderson 
527a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
528a768e4e9SRichard Henderson {
529a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
530a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
531a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
532a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
533a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
534a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
535a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
536a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
537a768e4e9SRichard Henderson     } else {
538a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
539a768e4e9SRichard Henderson     }
540a768e4e9SRichard Henderson }
541a768e4e9SRichard Henderson 
542951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
543951c6300SRichard Henderson {
544951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
545951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
546951c6300SRichard Henderson     } else {
547951c6300SRichard Henderson         TCGv_i32 t0, t1;
548951c6300SRichard Henderson 
549951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
550951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
551951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
552951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
553951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
554951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
555951c6300SRichard Henderson         tcg_temp_free_i32(t0);
556951c6300SRichard Henderson         tcg_temp_free_i32(t1);
557951c6300SRichard Henderson     }
558951c6300SRichard Henderson }
559951c6300SRichard Henderson 
560951c6300SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
561951c6300SRichard Henderson {
562951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
563951c6300SRichard Henderson     /* some cases can be optimized here */
564951c6300SRichard Henderson     if (arg2 == 0) {
565951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
566951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
567951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
568951c6300SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, t0);
569951c6300SRichard Henderson         tcg_temp_free_i32(t0);
570951c6300SRichard Henderson     } else {
571951c6300SRichard Henderson         TCGv_i32 t0, t1;
572951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
573951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
574951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
575951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
576951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
577951c6300SRichard Henderson         tcg_temp_free_i32(t0);
578951c6300SRichard Henderson         tcg_temp_free_i32(t1);
579951c6300SRichard Henderson     }
580951c6300SRichard Henderson }
581951c6300SRichard Henderson 
582951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
583951c6300SRichard Henderson {
584951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
585951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
586951c6300SRichard Henderson     } else {
587951c6300SRichard Henderson         TCGv_i32 t0, t1;
588951c6300SRichard Henderson 
589951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
590951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
591951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
592951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
593951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
594951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
595951c6300SRichard Henderson         tcg_temp_free_i32(t0);
596951c6300SRichard Henderson         tcg_temp_free_i32(t1);
597951c6300SRichard Henderson     }
598951c6300SRichard Henderson }
599951c6300SRichard Henderson 
600951c6300SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
601951c6300SRichard Henderson {
602951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
603951c6300SRichard Henderson     /* some cases can be optimized here */
604951c6300SRichard Henderson     if (arg2 == 0) {
605951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
606951c6300SRichard Henderson     } else {
607951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
608951c6300SRichard Henderson     }
609951c6300SRichard Henderson }
610951c6300SRichard Henderson 
611951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
612951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
613951c6300SRichard Henderson {
614951c6300SRichard Henderson     uint32_t mask;
615951c6300SRichard Henderson     TCGv_i32 t1;
616951c6300SRichard Henderson 
617951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
6180d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
619951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
620951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
621951c6300SRichard Henderson 
6220d0d309dSRichard Henderson     if (len == 32) {
623951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
624951c6300SRichard Henderson         return;
625951c6300SRichard Henderson     }
626951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
627951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
628951c6300SRichard Henderson         return;
629951c6300SRichard Henderson     }
630951c6300SRichard Henderson 
631951c6300SRichard Henderson     mask = (1u << len) - 1;
632951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
633951c6300SRichard Henderson 
634951c6300SRichard Henderson     if (ofs + len < 32) {
635951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
636951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
637951c6300SRichard Henderson     } else {
638951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
639951c6300SRichard Henderson     }
640951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
641951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
642951c6300SRichard Henderson 
643951c6300SRichard Henderson     tcg_temp_free_i32(t1);
644951c6300SRichard Henderson }
645951c6300SRichard Henderson 
64607cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
64707cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
64807cc68d5SRichard Henderson {
64907cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
65007cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
65107cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
65207cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
65307cc68d5SRichard Henderson 
65407cc68d5SRichard Henderson     if (ofs + len == 32) {
65507cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
65607cc68d5SRichard Henderson     } else if (ofs == 0) {
65707cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
65807cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
65907cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
66007cc68d5SRichard Henderson         TCGv_i32 zero = tcg_const_i32(0);
66107cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
66207cc68d5SRichard Henderson         tcg_temp_free_i32(zero);
66307cc68d5SRichard Henderson     } else {
66407cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
66507cc68d5SRichard Henderson            which allows ARG to stay live.  */
66607cc68d5SRichard Henderson         switch (len) {
66707cc68d5SRichard Henderson         case 16:
66807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
66907cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
67007cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
67107cc68d5SRichard Henderson                 return;
67207cc68d5SRichard Henderson             }
67307cc68d5SRichard Henderson             break;
67407cc68d5SRichard Henderson         case 8:
67507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
67607cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
67707cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
67807cc68d5SRichard Henderson                 return;
67907cc68d5SRichard Henderson             }
68007cc68d5SRichard Henderson             break;
68107cc68d5SRichard Henderson         }
68207cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
68307cc68d5SRichard Henderson         switch (ofs + len) {
68407cc68d5SRichard Henderson         case 16:
68507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
68607cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
68707cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
68807cc68d5SRichard Henderson                 return;
68907cc68d5SRichard Henderson             }
69007cc68d5SRichard Henderson             break;
69107cc68d5SRichard Henderson         case 8:
69207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
69307cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
69407cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
69507cc68d5SRichard Henderson                 return;
69607cc68d5SRichard Henderson             }
69707cc68d5SRichard Henderson             break;
69807cc68d5SRichard Henderson         }
69907cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
70007cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
70107cc68d5SRichard Henderson     }
70207cc68d5SRichard Henderson }
70307cc68d5SRichard Henderson 
7047ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
7057ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
7067ec8bab3SRichard Henderson {
7077ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7087ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7097ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7107ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7117ec8bab3SRichard Henderson 
7127ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7137ec8bab3SRichard Henderson     if (ofs + len == 32) {
7147ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
7157ec8bab3SRichard Henderson         return;
7167ec8bab3SRichard Henderson     }
7177ec8bab3SRichard Henderson     if (ofs == 0) {
7187ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
7197ec8bab3SRichard Henderson         return;
7207ec8bab3SRichard Henderson     }
7217ec8bab3SRichard Henderson 
7227ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
7237ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7247ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
7257ec8bab3SRichard Henderson         return;
7267ec8bab3SRichard Henderson     }
7277ec8bab3SRichard Henderson 
7287ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
7297ec8bab3SRichard Henderson     switch (ofs + len) {
7307ec8bab3SRichard Henderson     case 16:
7317ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7327ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7337ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7347ec8bab3SRichard Henderson             return;
7357ec8bab3SRichard Henderson         }
7367ec8bab3SRichard Henderson         break;
7377ec8bab3SRichard Henderson     case 8:
7387ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7397ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7407ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7417ec8bab3SRichard Henderson             return;
7427ec8bab3SRichard Henderson         }
7437ec8bab3SRichard Henderson         break;
7447ec8bab3SRichard Henderson     }
7457ec8bab3SRichard Henderson 
7467ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7477ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7487ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7497ec8bab3SRichard Henderson     switch (len) {
7507ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7517ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7527ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7537ec8bab3SRichard Henderson         break;
7547ec8bab3SRichard Henderson     default:
7557ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7567ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7577ec8bab3SRichard Henderson         break;
7587ec8bab3SRichard Henderson     }
7597ec8bab3SRichard Henderson }
7607ec8bab3SRichard Henderson 
7617ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7627ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7637ec8bab3SRichard Henderson {
7647ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7657ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7667ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7677ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7687ec8bab3SRichard Henderson 
7697ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7707ec8bab3SRichard Henderson     if (ofs + len == 32) {
7717ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
7727ec8bab3SRichard Henderson         return;
7737ec8bab3SRichard Henderson     }
7747ec8bab3SRichard Henderson     if (ofs == 0) {
7757ec8bab3SRichard Henderson         switch (len) {
7767ec8bab3SRichard Henderson         case 16:
7777ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7787ec8bab3SRichard Henderson             return;
7797ec8bab3SRichard Henderson         case 8:
7807ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
7817ec8bab3SRichard Henderson             return;
7827ec8bab3SRichard Henderson         }
7837ec8bab3SRichard Henderson     }
7847ec8bab3SRichard Henderson 
7857ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
7867ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7877ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
7887ec8bab3SRichard Henderson         return;
7897ec8bab3SRichard Henderson     }
7907ec8bab3SRichard Henderson 
7917ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
7927ec8bab3SRichard Henderson     switch (ofs + len) {
7937ec8bab3SRichard Henderson     case 16:
7947ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
7957ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
7967ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
7977ec8bab3SRichard Henderson             return;
7987ec8bab3SRichard Henderson         }
7997ec8bab3SRichard Henderson         break;
8007ec8bab3SRichard Henderson     case 8:
8017ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8027ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
8037ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
8047ec8bab3SRichard Henderson             return;
8057ec8bab3SRichard Henderson         }
8067ec8bab3SRichard Henderson         break;
8077ec8bab3SRichard Henderson     }
8087ec8bab3SRichard Henderson     switch (len) {
8097ec8bab3SRichard Henderson     case 16:
8107ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
8117ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8127ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
8137ec8bab3SRichard Henderson             return;
8147ec8bab3SRichard Henderson         }
8157ec8bab3SRichard Henderson         break;
8167ec8bab3SRichard Henderson     case 8:
8177ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8187ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8197ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
8207ec8bab3SRichard Henderson             return;
8217ec8bab3SRichard Henderson         }
8227ec8bab3SRichard Henderson         break;
8237ec8bab3SRichard Henderson     }
8247ec8bab3SRichard Henderson 
8257ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
8267ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
8277ec8bab3SRichard Henderson }
8287ec8bab3SRichard Henderson 
829951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
830951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
831951c6300SRichard Henderson {
83237ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
83337ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
83437ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
83537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
83637ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
837951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
838951c6300SRichard Henderson     } else {
839951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
840951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
841951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
842951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
843951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
844951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
845951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
846951c6300SRichard Henderson         tcg_temp_free_i32(t0);
847951c6300SRichard Henderson         tcg_temp_free_i32(t1);
848951c6300SRichard Henderson     }
849951c6300SRichard Henderson }
850951c6300SRichard Henderson 
851951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
852951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
853951c6300SRichard Henderson {
854951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
855951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
856951c6300SRichard Henderson     } else {
857951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
858951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
859951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
860951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
861951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
862951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
863951c6300SRichard Henderson         tcg_temp_free_i64(t0);
864951c6300SRichard Henderson         tcg_temp_free_i64(t1);
865951c6300SRichard Henderson     }
866951c6300SRichard Henderson }
867951c6300SRichard Henderson 
868951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
869951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
870951c6300SRichard Henderson {
871951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
872951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
873951c6300SRichard Henderson     } else {
874951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
875951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
876951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
877951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
878951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
879951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
880951c6300SRichard Henderson         tcg_temp_free_i64(t0);
881951c6300SRichard Henderson         tcg_temp_free_i64(t1);
882951c6300SRichard Henderson     }
883951c6300SRichard Henderson }
884951c6300SRichard Henderson 
885951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
886951c6300SRichard Henderson {
887951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
888951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
889951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
890951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
891951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
892951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
893951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
894951c6300SRichard Henderson         tcg_temp_free_i32(t);
895951c6300SRichard Henderson     } else {
896951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
897951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
898951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
899951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
900951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
901951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
902951c6300SRichard Henderson         tcg_temp_free_i64(t0);
903951c6300SRichard Henderson         tcg_temp_free_i64(t1);
904951c6300SRichard Henderson     }
905951c6300SRichard Henderson }
906951c6300SRichard Henderson 
907951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
908951c6300SRichard Henderson {
909951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
910951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
911951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
912951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
913951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
914951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
915951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
916951c6300SRichard Henderson         tcg_temp_free_i32(t);
917951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
918951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
919951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
920951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
921951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
922951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
923951c6300SRichard Henderson         /* Adjust for negative inputs.  */
924951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
925951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
926951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
927951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
928951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
929951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
930951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
931951c6300SRichard Henderson         tcg_temp_free_i32(t0);
932951c6300SRichard Henderson         tcg_temp_free_i32(t1);
933951c6300SRichard Henderson         tcg_temp_free_i32(t2);
934951c6300SRichard Henderson         tcg_temp_free_i32(t3);
935951c6300SRichard Henderson     } else {
936951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
937951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
938951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
939951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
940951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
941951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
942951c6300SRichard Henderson         tcg_temp_free_i64(t0);
943951c6300SRichard Henderson         tcg_temp_free_i64(t1);
944951c6300SRichard Henderson     }
945951c6300SRichard Henderson }
946951c6300SRichard Henderson 
9475087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9485087abfbSRichard Henderson {
9495087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9505087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9515087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9525087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9535087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9545087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9555087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9565087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9575087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9585087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9595087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9605087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9615087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9625087abfbSRichard Henderson     } else {
9635087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9645087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9655087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9665087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9675087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9685087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9695087abfbSRichard Henderson         tcg_temp_free_i64(t0);
9705087abfbSRichard Henderson         tcg_temp_free_i64(t1);
9715087abfbSRichard Henderson     }
9725087abfbSRichard Henderson }
9735087abfbSRichard Henderson 
974951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
975951c6300SRichard Henderson {
976951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
977951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
978951c6300SRichard Henderson     } else {
979951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
980951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
981951c6300SRichard Henderson     }
982951c6300SRichard Henderson }
983951c6300SRichard Henderson 
984951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
985951c6300SRichard Henderson {
986951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
987951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
988951c6300SRichard Henderson     } else {
989951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
990951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
991951c6300SRichard Henderson     }
992951c6300SRichard Henderson }
993951c6300SRichard Henderson 
994951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
995951c6300SRichard Henderson {
996951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
997951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
998951c6300SRichard Henderson     } else {
999951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
1000951c6300SRichard Henderson     }
1001951c6300SRichard Henderson }
1002951c6300SRichard Henderson 
1003951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
1004951c6300SRichard Henderson {
1005951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
1006951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
1007951c6300SRichard Henderson     } else {
1008951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1009951c6300SRichard Henderson     }
1010951c6300SRichard Henderson }
1011951c6300SRichard Henderson 
1012951c6300SRichard Henderson /* Note: we assume the two high bytes are set to zero */
1013951c6300SRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
1014951c6300SRichard Henderson {
1015951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
1016951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
1017951c6300SRichard Henderson     } else {
1018951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1019951c6300SRichard Henderson 
1020951c6300SRichard Henderson         tcg_gen_ext8u_i32(t0, arg);
1021951c6300SRichard Henderson         tcg_gen_shli_i32(t0, t0, 8);
1022951c6300SRichard Henderson         tcg_gen_shri_i32(ret, arg, 8);
1023951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t0);
1024951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1025951c6300SRichard Henderson     }
1026951c6300SRichard Henderson }
1027951c6300SRichard Henderson 
1028951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1029951c6300SRichard Henderson {
1030951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1031951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
1032951c6300SRichard Henderson     } else {
1033951c6300SRichard Henderson         TCGv_i32 t0, t1;
1034951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1035951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1036951c6300SRichard Henderson 
1037951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg, 24);
1038951c6300SRichard Henderson 
1039951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg, 0x0000ff00);
1040951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);
1041951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
1042951c6300SRichard Henderson 
1043951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 8);
1044951c6300SRichard Henderson         tcg_gen_andi_i32(t1, t1, 0x0000ff00);
1045951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
1046951c6300SRichard Henderson 
1047951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 24);
1048951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1049951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1050951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1051951c6300SRichard Henderson     }
1052951c6300SRichard Henderson }
1053951c6300SRichard Henderson 
1054951c6300SRichard Henderson /* 64-bit ops */
1055951c6300SRichard Henderson 
1056951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1057951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1058951c6300SRichard Henderson 
1059951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1060951c6300SRichard Henderson {
1061951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1062951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1063951c6300SRichard Henderson }
1064951c6300SRichard Henderson 
1065951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1066951c6300SRichard Henderson {
1067951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1068951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1069951c6300SRichard Henderson }
1070951c6300SRichard Henderson 
1071951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1072951c6300SRichard Henderson {
1073951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1074951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1075951c6300SRichard Henderson }
1076951c6300SRichard Henderson 
1077951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1078951c6300SRichard Henderson {
1079951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1080951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1081951c6300SRichard Henderson }
1082951c6300SRichard Henderson 
1083951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1084951c6300SRichard Henderson {
1085951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
10863ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1087951c6300SRichard Henderson }
1088951c6300SRichard Henderson 
1089951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1090951c6300SRichard Henderson {
1091951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1092951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1093951c6300SRichard Henderson }
1094951c6300SRichard Henderson 
1095951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1096951c6300SRichard Henderson {
1097951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1098951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1099951c6300SRichard Henderson }
1100951c6300SRichard Henderson 
1101951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1102951c6300SRichard Henderson {
1103951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1104951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1105951c6300SRichard Henderson }
1106951c6300SRichard Henderson 
1107951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1108951c6300SRichard Henderson {
1109951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1110951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1111951c6300SRichard Henderson }
1112951c6300SRichard Henderson 
1113951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1114951c6300SRichard Henderson {
1115951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1116951c6300SRichard Henderson        they cannot be the same temporary */
1117cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1118951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1119951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1120951c6300SRichard Henderson #else
1121951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1122951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1123951c6300SRichard Henderson #endif
1124951c6300SRichard Henderson }
1125951c6300SRichard Henderson 
1126951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1127951c6300SRichard Henderson {
1128cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1129951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1130951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1131951c6300SRichard Henderson #else
1132951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1133951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1134951c6300SRichard Henderson #endif
1135951c6300SRichard Henderson }
1136951c6300SRichard Henderson 
1137951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1138951c6300SRichard Henderson {
1139951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1140951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1141951c6300SRichard Henderson }
1142951c6300SRichard Henderson 
1143951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1144951c6300SRichard Henderson {
1145951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1146951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1147951c6300SRichard Henderson }
1148951c6300SRichard Henderson 
1149951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1150951c6300SRichard Henderson {
1151951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1152951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1153951c6300SRichard Henderson }
1154951c6300SRichard Henderson 
1155951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1156951c6300SRichard Henderson {
1157951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1158951c6300SRichard Henderson }
1159951c6300SRichard Henderson 
1160951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1161951c6300SRichard Henderson {
1162951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1163951c6300SRichard Henderson }
1164951c6300SRichard Henderson 
1165951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1166951c6300SRichard Henderson {
1167951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1168951c6300SRichard Henderson }
1169951c6300SRichard Henderson 
1170951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1171951c6300SRichard Henderson {
1172951c6300SRichard Henderson     TCGv_i64 t0;
1173951c6300SRichard Henderson     TCGv_i32 t1;
1174951c6300SRichard Henderson 
1175951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1176951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1177951c6300SRichard Henderson 
1178951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1179951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1180951c6300SRichard Henderson 
1181951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1182951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1183951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1184951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1185951c6300SRichard Henderson 
1186951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1187951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1188951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1189951c6300SRichard Henderson }
1190951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1191951c6300SRichard Henderson 
1192951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1193951c6300SRichard Henderson {
1194951c6300SRichard Henderson     /* some cases can be optimized here */
1195951c6300SRichard Henderson     if (arg2 == 0) {
1196951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1197951c6300SRichard Henderson     } else {
1198951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1199951c6300SRichard Henderson         tcg_gen_add_i64(ret, arg1, t0);
1200951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1201951c6300SRichard Henderson     }
1202951c6300SRichard Henderson }
1203951c6300SRichard Henderson 
1204951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1205951c6300SRichard Henderson {
1206951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1207951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1208951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
1209951c6300SRichard Henderson     } else {
1210951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg1);
1211951c6300SRichard Henderson         tcg_gen_sub_i64(ret, t0, arg2);
1212951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1213951c6300SRichard Henderson     }
1214951c6300SRichard Henderson }
1215951c6300SRichard Henderson 
1216951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1217951c6300SRichard Henderson {
1218951c6300SRichard Henderson     /* some cases can be optimized here */
1219951c6300SRichard Henderson     if (arg2 == 0) {
1220951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1221951c6300SRichard Henderson     } else {
1222951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1223951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1224951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1225951c6300SRichard Henderson     }
1226951c6300SRichard Henderson }
1227951c6300SRichard Henderson 
1228951c6300SRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
1229951c6300SRichard Henderson {
12303a13c3f3SRichard Henderson     TCGv_i64 t0;
12313a13c3f3SRichard Henderson 
12323a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1233951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1234951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12353a13c3f3SRichard Henderson         return;
12363a13c3f3SRichard Henderson     }
12373a13c3f3SRichard Henderson 
1238951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1239951c6300SRichard Henderson     switch (arg2) {
1240951c6300SRichard Henderson     case 0:
1241951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1242951c6300SRichard Henderson         return;
1243951c6300SRichard Henderson     case 0xffffffffffffffffull:
1244951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1245951c6300SRichard Henderson         return;
1246951c6300SRichard Henderson     case 0xffull:
1247951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1248951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1249951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1250951c6300SRichard Henderson             return;
1251951c6300SRichard Henderson         }
1252951c6300SRichard Henderson         break;
1253951c6300SRichard Henderson     case 0xffffu:
1254951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1255951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1256951c6300SRichard Henderson             return;
1257951c6300SRichard Henderson         }
1258951c6300SRichard Henderson         break;
1259951c6300SRichard Henderson     case 0xffffffffull:
1260951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1261951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1262951c6300SRichard Henderson             return;
1263951c6300SRichard Henderson         }
1264951c6300SRichard Henderson         break;
1265951c6300SRichard Henderson     }
1266951c6300SRichard Henderson     t0 = tcg_const_i64(arg2);
1267951c6300SRichard Henderson     tcg_gen_and_i64(ret, arg1, t0);
1268951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1269951c6300SRichard Henderson }
1270951c6300SRichard Henderson 
1271951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1272951c6300SRichard Henderson {
12733a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1274951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1275951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12763a13c3f3SRichard Henderson         return;
12773a13c3f3SRichard Henderson     }
1278951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1279951c6300SRichard Henderson     if (arg2 == -1) {
1280951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1281951c6300SRichard Henderson     } else if (arg2 == 0) {
1282951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1283951c6300SRichard Henderson     } else {
1284951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1285951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1286951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1287951c6300SRichard Henderson     }
1288951c6300SRichard Henderson }
1289951c6300SRichard Henderson 
1290951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1291951c6300SRichard Henderson {
12923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1293951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1294951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12953a13c3f3SRichard Henderson         return;
12963a13c3f3SRichard Henderson     }
1297951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1298951c6300SRichard Henderson     if (arg2 == 0) {
1299951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1300951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1301951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1302951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1303951c6300SRichard Henderson     } else {
1304951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1305951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, t0);
1306951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1307951c6300SRichard Henderson     }
1308951c6300SRichard Henderson }
1309951c6300SRichard Henderson 
1310951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1311951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1312951c6300SRichard Henderson {
1313951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1314951c6300SRichard Henderson     if (c == 0) {
1315951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1316951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1317951c6300SRichard Henderson     } else if (c >= 32) {
1318951c6300SRichard Henderson         c -= 32;
1319951c6300SRichard Henderson         if (right) {
1320951c6300SRichard Henderson             if (arith) {
1321951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1322951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1323951c6300SRichard Henderson             } else {
1324951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1325951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1326951c6300SRichard Henderson             }
1327951c6300SRichard Henderson         } else {
1328951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1329951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1330951c6300SRichard Henderson         }
1331951c6300SRichard Henderson     } else {
1332951c6300SRichard Henderson         TCGv_i32 t0, t1;
1333951c6300SRichard Henderson 
1334951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1335951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1336951c6300SRichard Henderson         if (right) {
1337951c6300SRichard Henderson             tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
1338951c6300SRichard Henderson             if (arith) {
1339951c6300SRichard Henderson                 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
1340951c6300SRichard Henderson             } else {
1341951c6300SRichard Henderson                 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
1342951c6300SRichard Henderson             }
1343951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1344951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
1345951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
1346951c6300SRichard Henderson         } else {
1347951c6300SRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
1348951c6300SRichard Henderson             /* Note: ret can be the same as arg1, so we use t1 */
1349951c6300SRichard Henderson             tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
1350951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1351951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
1352951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1353951c6300SRichard Henderson         }
1354951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1355951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1356951c6300SRichard Henderson     }
1357951c6300SRichard Henderson }
1358951c6300SRichard Henderson 
1359951c6300SRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1360951c6300SRichard Henderson {
1361951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
13623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13633a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
13643a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1365951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1366951c6300SRichard Henderson     } else {
1367951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1368951c6300SRichard Henderson         tcg_gen_shl_i64(ret, arg1, t0);
1369951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1370951c6300SRichard Henderson     }
1371951c6300SRichard Henderson }
1372951c6300SRichard Henderson 
1373951c6300SRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1374951c6300SRichard Henderson {
1375951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
13763a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13773a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
13783a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1379951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1380951c6300SRichard Henderson     } else {
1381951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1382951c6300SRichard Henderson         tcg_gen_shr_i64(ret, arg1, t0);
1383951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1384951c6300SRichard Henderson     }
1385951c6300SRichard Henderson }
1386951c6300SRichard Henderson 
1387951c6300SRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1388951c6300SRichard Henderson {
1389951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
13903a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13913a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
13923a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1393951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1394951c6300SRichard Henderson     } else {
1395951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1396951c6300SRichard Henderson         tcg_gen_sar_i64(ret, arg1, t0);
1397951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1398951c6300SRichard Henderson     }
1399951c6300SRichard Henderson }
1400951c6300SRichard Henderson 
140142a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1402951c6300SRichard Henderson {
1403951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
140442a268c2SRichard Henderson         tcg_gen_br(l);
1405951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
14063a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1407951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1408951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
140942a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14103a13c3f3SRichard Henderson         } else {
141142a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
141242a268c2SRichard Henderson                               label_arg(l));
14133a13c3f3SRichard Henderson         }
1414951c6300SRichard Henderson     }
1415951c6300SRichard Henderson }
1416951c6300SRichard Henderson 
141742a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1418951c6300SRichard Henderson {
1419951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
142042a268c2SRichard Henderson         tcg_gen_br(l);
1421951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1422951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
142342a268c2SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, t0, l);
1424951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1425951c6300SRichard Henderson     }
1426951c6300SRichard Henderson }
1427951c6300SRichard Henderson 
1428951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1429951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1430951c6300SRichard Henderson {
1431951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1432951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1433951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1434951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1435951c6300SRichard Henderson     } else {
14363a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1437951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1438951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1439951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1440951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
14413a13c3f3SRichard Henderson         } else {
1442951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
14433a13c3f3SRichard Henderson         }
1444951c6300SRichard Henderson     }
1445951c6300SRichard Henderson }
1446951c6300SRichard Henderson 
1447951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1448951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1449951c6300SRichard Henderson {
1450951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1451951c6300SRichard Henderson     tcg_gen_setcond_i64(cond, ret, arg1, t0);
1452951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1453951c6300SRichard Henderson }
1454951c6300SRichard Henderson 
1455951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1456951c6300SRichard Henderson {
1457951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1458951c6300SRichard Henderson     tcg_gen_mul_i64(ret, arg1, t0);
1459951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1460951c6300SRichard Henderson }
1461951c6300SRichard Henderson 
1462951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1463951c6300SRichard Henderson {
1464951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1465951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1466951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1467951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1468951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1469951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1470951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1471951c6300SRichard Henderson     } else {
1472951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1473951c6300SRichard Henderson     }
1474951c6300SRichard Henderson }
1475951c6300SRichard Henderson 
1476951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1477951c6300SRichard Henderson {
1478951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1479951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1480951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1481951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1482951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1483951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1484951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1485951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1486951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1487951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1488951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1489951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1490951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1491951c6300SRichard Henderson     } else {
1492951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1493951c6300SRichard Henderson     }
1494951c6300SRichard Henderson }
1495951c6300SRichard Henderson 
1496951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1497951c6300SRichard Henderson {
1498951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1499951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1500951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1501951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1502951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1503951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1504951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1505951c6300SRichard Henderson     } else {
1506951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1507951c6300SRichard Henderson     }
1508951c6300SRichard Henderson }
1509951c6300SRichard Henderson 
1510951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1511951c6300SRichard Henderson {
1512951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1513951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1514951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1515951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1516951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1517951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1518951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1519951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1520951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1521951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1522951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1523951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1524951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1525951c6300SRichard Henderson     } else {
1526951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1527951c6300SRichard Henderson     }
1528951c6300SRichard Henderson }
1529951c6300SRichard Henderson 
1530951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1531951c6300SRichard Henderson {
15323a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1533951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1534951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15353a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1536951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1537951c6300SRichard Henderson     } else {
1538951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1539951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1540951c6300SRichard Henderson     }
1541951c6300SRichard Henderson }
1542951c6300SRichard Henderson 
1543951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1544951c6300SRichard Henderson {
15453a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1546951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1547951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15483a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1549951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1550951c6300SRichard Henderson     } else {
1551951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1552951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1553951c6300SRichard Henderson     }
1554951c6300SRichard Henderson }
1555951c6300SRichard Henderson 
1556951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1557951c6300SRichard Henderson {
15583a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1559951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1560951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15613a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1562951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1563951c6300SRichard Henderson     } else {
1564951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1565951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1566951c6300SRichard Henderson     }
1567951c6300SRichard Henderson }
1568951c6300SRichard Henderson 
1569951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1570951c6300SRichard Henderson {
15713a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1572951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1573951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15743a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1575951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1576951c6300SRichard Henderson     } else {
1577951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1578951c6300SRichard Henderson     }
1579951c6300SRichard Henderson }
1580951c6300SRichard Henderson 
1581951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1582951c6300SRichard Henderson {
15833a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1584951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1585951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15863a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1587951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1588951c6300SRichard Henderson     } else {
1589951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1590951c6300SRichard Henderson     }
1591951c6300SRichard Henderson }
1592951c6300SRichard Henderson 
1593951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1594951c6300SRichard Henderson {
15953a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1596951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1597951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
15983a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1599951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1600951c6300SRichard Henderson     } else {
1601951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1602951c6300SRichard Henderson     }
1603951c6300SRichard Henderson }
1604951c6300SRichard Henderson 
1605951c6300SRichard Henderson /* Note: we assume the six high bytes are set to zero */
1606951c6300SRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
1607951c6300SRichard Henderson {
16083a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1609951c6300SRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1610951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16113a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
1612951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
1613951c6300SRichard Henderson     } else {
1614951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1615951c6300SRichard Henderson 
1616951c6300SRichard Henderson         tcg_gen_ext8u_i64(t0, arg);
1617951c6300SRichard Henderson         tcg_gen_shli_i64(t0, t0, 8);
1618951c6300SRichard Henderson         tcg_gen_shri_i64(ret, arg, 8);
1619951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t0);
1620951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1621951c6300SRichard Henderson     }
1622951c6300SRichard Henderson }
1623951c6300SRichard Henderson 
1624951c6300SRichard Henderson /* Note: we assume the four high bytes are set to zero */
1625951c6300SRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
1626951c6300SRichard Henderson {
16273a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1628951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1629951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16303a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
1631951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
1632951c6300SRichard Henderson     } else {
1633951c6300SRichard Henderson         TCGv_i64 t0, t1;
1634951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1635951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1636951c6300SRichard Henderson 
1637951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 24);
1638951c6300SRichard Henderson         tcg_gen_ext32u_i64(t0, t0);
1639951c6300SRichard Henderson 
1640951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1641951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1642951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1643951c6300SRichard Henderson 
1644951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1645951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1646951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1647951c6300SRichard Henderson 
1648951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1649951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1650951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1651951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1652951c6300SRichard Henderson     }
1653951c6300SRichard Henderson }
1654951c6300SRichard Henderson 
1655951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1656951c6300SRichard Henderson {
16573a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1658951c6300SRichard Henderson         TCGv_i32 t0, t1;
1659951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1660951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1661951c6300SRichard Henderson 
1662951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1663951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1664951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1665951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1666951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1667951c6300SRichard Henderson         tcg_temp_free_i32(t1);
16683a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1669951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
1670951c6300SRichard Henderson     } else {
1671951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1672951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1673951c6300SRichard Henderson 
1674951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 56);
1675951c6300SRichard Henderson 
1676951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1677951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 40);
1678951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1679951c6300SRichard Henderson 
1680951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x00ff0000);
1681951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 24);
1682951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1683951c6300SRichard Henderson 
1684951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0xff000000);
1685951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1686951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1687951c6300SRichard Henderson 
1688951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1689951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0xff000000);
1690951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1691951c6300SRichard Henderson 
1692951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1693951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x00ff0000);
1694951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1695951c6300SRichard Henderson 
1696951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 40);
1697951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1698951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1699951c6300SRichard Henderson 
1700951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 56);
1701951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1702951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1703951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1704951c6300SRichard Henderson     }
1705951c6300SRichard Henderson }
1706951c6300SRichard Henderson 
1707951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1708951c6300SRichard Henderson {
17093a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17103a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17113a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
17123a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1713951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1714951c6300SRichard Henderson     } else {
1715951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1716951c6300SRichard Henderson     }
1717951c6300SRichard Henderson }
1718951c6300SRichard Henderson 
1719951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1720951c6300SRichard Henderson {
17213a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17223a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17233a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17243a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1725951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1726951c6300SRichard Henderson     } else {
1727951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1728951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1729951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1730951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1731951c6300SRichard Henderson     }
1732951c6300SRichard Henderson }
1733951c6300SRichard Henderson 
1734951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1735951c6300SRichard Henderson {
17363a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17373a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17383a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17393a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1740951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1741951c6300SRichard Henderson     } else {
1742951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1743951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1744951c6300SRichard Henderson     }
1745951c6300SRichard Henderson }
1746951c6300SRichard Henderson 
1747951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1748951c6300SRichard Henderson {
17493a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17503a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17513a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17523a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1753951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1754951c6300SRichard Henderson     } else {
1755951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1756951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1757951c6300SRichard Henderson     }
1758951c6300SRichard Henderson }
1759951c6300SRichard Henderson 
1760951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1761951c6300SRichard Henderson {
17623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17633a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17643a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17653a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1766951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1767951c6300SRichard Henderson     } else {
1768951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1769951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1770951c6300SRichard Henderson     }
1771951c6300SRichard Henderson }
1772951c6300SRichard Henderson 
1773951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1774951c6300SRichard Henderson {
17753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17763a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17773a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17783a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1779951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1780951c6300SRichard Henderson     } else {
1781951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1782951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1783951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1784951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1785951c6300SRichard Henderson     }
1786951c6300SRichard Henderson }
1787951c6300SRichard Henderson 
17880e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
17890e28d006SRichard Henderson {
17900e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
17910e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
17920e28d006SRichard Henderson     } else {
17930e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
17940e28d006SRichard Henderson     }
17950e28d006SRichard Henderson }
17960e28d006SRichard Henderson 
17970e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
17980e28d006SRichard Henderson {
17990e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18000e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
18010e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18020e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32((uint32_t)arg2 - 32);
18030e28d006SRichard Henderson         tcg_gen_clz_i32(t, TCGV_LOW(arg1), t);
18040e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
18050e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
18060e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18070e28d006SRichard Henderson         tcg_temp_free_i32(t);
18080e28d006SRichard Henderson     } else {
18090e28d006SRichard Henderson         TCGv_i64 t = tcg_const_i64(arg2);
18100e28d006SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t);
18110e28d006SRichard Henderson         tcg_temp_free_i64(t);
18120e28d006SRichard Henderson     }
18130e28d006SRichard Henderson }
18140e28d006SRichard Henderson 
18150e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18160e28d006SRichard Henderson {
18170e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
18180e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
181914e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
182014e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
182114e99210SRichard Henderson 
182214e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
182314e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
182414e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
182514e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
182614e99210SRichard Henderson         } else {
182714e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
182814e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
182914e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
183014e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
183114e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
183214e99210SRichard Henderson         }
183314e99210SRichard Henderson         z = tcg_const_i64(0);
183414e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
183514e99210SRichard Henderson         tcg_temp_free_i64(t);
183614e99210SRichard Henderson         tcg_temp_free_i64(z);
18370e28d006SRichard Henderson     } else {
18380e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
18390e28d006SRichard Henderson     }
18400e28d006SRichard Henderson }
18410e28d006SRichard Henderson 
18420e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18430e28d006SRichard Henderson {
18440e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18450e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
18460e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18470e28d006SRichard Henderson         TCGv_i32 t32 = tcg_const_i32((uint32_t)arg2 - 32);
18480e28d006SRichard Henderson         tcg_gen_ctz_i32(t32, TCGV_HIGH(arg1), t32);
18490e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
18500e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
18510e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18520e28d006SRichard Henderson         tcg_temp_free_i32(t32);
185314e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
185414e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
185514e99210SRichard Henderson                && arg2 == 64) {
185614e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
185714e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
185814e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
185914e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
186014e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
186114e99210SRichard Henderson         tcg_temp_free_i64(t);
18620e28d006SRichard Henderson     } else {
18630e28d006SRichard Henderson         TCGv_i64 t64 = tcg_const_i64(arg2);
18640e28d006SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t64);
18650e28d006SRichard Henderson         tcg_temp_free_i64(t64);
18660e28d006SRichard Henderson     }
18670e28d006SRichard Henderson }
18680e28d006SRichard Henderson 
1869086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
1870086920c2SRichard Henderson {
1871086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
1872086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1873086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
1874086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
1875086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
1876086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
1877086920c2SRichard Henderson         tcg_temp_free_i64(t);
1878086920c2SRichard Henderson     } else {
1879086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
1880086920c2SRichard Henderson     }
1881086920c2SRichard Henderson }
1882086920c2SRichard Henderson 
1883a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
1884a768e4e9SRichard Henderson {
1885a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
1886a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
1887a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
1888a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1889a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1890a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
1891a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1892a768e4e9SRichard Henderson     } else {
1893a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
1894a768e4e9SRichard Henderson     }
1895a768e4e9SRichard Henderson }
1896a768e4e9SRichard Henderson 
1897951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1898951c6300SRichard Henderson {
1899951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1900951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1901951c6300SRichard Henderson     } else {
1902951c6300SRichard Henderson         TCGv_i64 t0, t1;
1903951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1904951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1905951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1906951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1907951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1908951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1909951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1910951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1911951c6300SRichard Henderson     }
1912951c6300SRichard Henderson }
1913951c6300SRichard Henderson 
1914951c6300SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1915951c6300SRichard Henderson {
1916951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1917951c6300SRichard Henderson     /* some cases can be optimized here */
1918951c6300SRichard Henderson     if (arg2 == 0) {
1919951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1920951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
1921951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1922951c6300SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, t0);
1923951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1924951c6300SRichard Henderson     } else {
1925951c6300SRichard Henderson         TCGv_i64 t0, t1;
1926951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1927951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1928951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
1929951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
1930951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1931951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1932951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1933951c6300SRichard Henderson     }
1934951c6300SRichard Henderson }
1935951c6300SRichard Henderson 
1936951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1937951c6300SRichard Henderson {
1938951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1939951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
1940951c6300SRichard Henderson     } else {
1941951c6300SRichard Henderson         TCGv_i64 t0, t1;
1942951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1943951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1944951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
1945951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1946951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
1947951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1948951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1949951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1950951c6300SRichard Henderson     }
1951951c6300SRichard Henderson }
1952951c6300SRichard Henderson 
1953951c6300SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1954951c6300SRichard Henderson {
1955951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1956951c6300SRichard Henderson     /* some cases can be optimized here */
1957951c6300SRichard Henderson     if (arg2 == 0) {
1958951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1959951c6300SRichard Henderson     } else {
1960951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
1961951c6300SRichard Henderson     }
1962951c6300SRichard Henderson }
1963951c6300SRichard Henderson 
1964951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
1965951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
1966951c6300SRichard Henderson {
1967951c6300SRichard Henderson     uint64_t mask;
1968951c6300SRichard Henderson     TCGv_i64 t1;
1969951c6300SRichard Henderson 
1970951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
19710d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
1972951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
1973951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
1974951c6300SRichard Henderson 
19750d0d309dSRichard Henderson     if (len == 64) {
1976951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
1977951c6300SRichard Henderson         return;
1978951c6300SRichard Henderson     }
1979951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
1980951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
1981951c6300SRichard Henderson         return;
1982951c6300SRichard Henderson     }
1983951c6300SRichard Henderson 
19843a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1985951c6300SRichard Henderson         if (ofs >= 32) {
1986951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
1987951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
1988951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1989951c6300SRichard Henderson             return;
1990951c6300SRichard Henderson         }
1991951c6300SRichard Henderson         if (ofs + len <= 32) {
1992951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
1993951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
1994951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1995951c6300SRichard Henderson             return;
1996951c6300SRichard Henderson         }
19973a13c3f3SRichard Henderson     }
1998951c6300SRichard Henderson 
1999951c6300SRichard Henderson     mask = (1ull << len) - 1;
2000951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2001951c6300SRichard Henderson 
2002951c6300SRichard Henderson     if (ofs + len < 64) {
2003951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2004951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2005951c6300SRichard Henderson     } else {
2006951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2007951c6300SRichard Henderson     }
2008951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2009951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2010951c6300SRichard Henderson 
2011951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2012951c6300SRichard Henderson }
2013951c6300SRichard Henderson 
201407cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
201507cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
201607cc68d5SRichard Henderson {
201707cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
201807cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
201907cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
202007cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
202107cc68d5SRichard Henderson 
202207cc68d5SRichard Henderson     if (ofs + len == 64) {
202307cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
202407cc68d5SRichard Henderson     } else if (ofs == 0) {
202507cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
202607cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
202707cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
202807cc68d5SRichard Henderson         TCGv_i64 zero = tcg_const_i64(0);
202907cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
203007cc68d5SRichard Henderson         tcg_temp_free_i64(zero);
203107cc68d5SRichard Henderson     } else {
203207cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
203307cc68d5SRichard Henderson             if (ofs >= 32) {
203407cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
203507cc68d5SRichard Henderson                                       ofs - 32, len);
203607cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
203707cc68d5SRichard Henderson                 return;
203807cc68d5SRichard Henderson             }
203907cc68d5SRichard Henderson             if (ofs + len <= 32) {
204007cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
204107cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
204207cc68d5SRichard Henderson                 return;
204307cc68d5SRichard Henderson             }
204407cc68d5SRichard Henderson         }
204507cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
204607cc68d5SRichard Henderson            which allows ARG to stay live.  */
204707cc68d5SRichard Henderson         switch (len) {
204807cc68d5SRichard Henderson         case 32:
204907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
205007cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
205107cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
205207cc68d5SRichard Henderson                 return;
205307cc68d5SRichard Henderson             }
205407cc68d5SRichard Henderson             break;
205507cc68d5SRichard Henderson         case 16:
205607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
205707cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
205807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
205907cc68d5SRichard Henderson                 return;
206007cc68d5SRichard Henderson             }
206107cc68d5SRichard Henderson             break;
206207cc68d5SRichard Henderson         case 8:
206307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
206407cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
206507cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
206607cc68d5SRichard Henderson                 return;
206707cc68d5SRichard Henderson             }
206807cc68d5SRichard Henderson             break;
206907cc68d5SRichard Henderson         }
207007cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
207107cc68d5SRichard Henderson         switch (ofs + len) {
207207cc68d5SRichard Henderson         case 32:
207307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
207407cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
207507cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
207607cc68d5SRichard Henderson                 return;
207707cc68d5SRichard Henderson             }
207807cc68d5SRichard Henderson             break;
207907cc68d5SRichard Henderson         case 16:
208007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
208107cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
208207cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
208307cc68d5SRichard Henderson                 return;
208407cc68d5SRichard Henderson             }
208507cc68d5SRichard Henderson             break;
208607cc68d5SRichard Henderson         case 8:
208707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
208807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
208907cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
209007cc68d5SRichard Henderson                 return;
209107cc68d5SRichard Henderson             }
209207cc68d5SRichard Henderson             break;
209307cc68d5SRichard Henderson         }
209407cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
209507cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
209607cc68d5SRichard Henderson     }
209707cc68d5SRichard Henderson }
209807cc68d5SRichard Henderson 
20997ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
21007ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
21017ec8bab3SRichard Henderson {
21027ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
21037ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
21047ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
21057ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
21067ec8bab3SRichard Henderson 
21077ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
21087ec8bab3SRichard Henderson     if (ofs + len == 64) {
21097ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
21107ec8bab3SRichard Henderson         return;
21117ec8bab3SRichard Henderson     }
21127ec8bab3SRichard Henderson     if (ofs == 0) {
21137ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
21147ec8bab3SRichard Henderson         return;
21157ec8bab3SRichard Henderson     }
21167ec8bab3SRichard Henderson 
21177ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
21187ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
21197ec8bab3SRichard Henderson         if (ofs >= 32) {
21207ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
21217ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21227ec8bab3SRichard Henderson             return;
21237ec8bab3SRichard Henderson         }
21247ec8bab3SRichard Henderson         if (ofs + len <= 32) {
21257ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
21267ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21277ec8bab3SRichard Henderson             return;
21287ec8bab3SRichard Henderson         }
21297ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
21307ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
21317ec8bab3SRichard Henderson         goto do_shift_and;
21327ec8bab3SRichard Henderson     }
21337ec8bab3SRichard Henderson 
21347ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
21357ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
21367ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
21377ec8bab3SRichard Henderson         return;
21387ec8bab3SRichard Henderson     }
21397ec8bab3SRichard Henderson 
21407ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
21417ec8bab3SRichard Henderson     switch (ofs + len) {
21427ec8bab3SRichard Henderson     case 32:
21437ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
21447ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
21457ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21467ec8bab3SRichard Henderson             return;
21477ec8bab3SRichard Henderson         }
21487ec8bab3SRichard Henderson         break;
21497ec8bab3SRichard Henderson     case 16:
21507ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
21517ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
21527ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21537ec8bab3SRichard Henderson             return;
21547ec8bab3SRichard Henderson         }
21557ec8bab3SRichard Henderson         break;
21567ec8bab3SRichard Henderson     case 8:
21577ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
21587ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
21597ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21607ec8bab3SRichard Henderson             return;
21617ec8bab3SRichard Henderson         }
21627ec8bab3SRichard Henderson         break;
21637ec8bab3SRichard Henderson     }
21647ec8bab3SRichard Henderson 
21657ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
21667ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
21677ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
21687ec8bab3SRichard Henderson     switch (len) {
21697ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
21707ec8bab3SRichard Henderson     do_shift_and:
21717ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
21727ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
21737ec8bab3SRichard Henderson         break;
21747ec8bab3SRichard Henderson     default:
21757ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
21767ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
21777ec8bab3SRichard Henderson         break;
21787ec8bab3SRichard Henderson     }
21797ec8bab3SRichard Henderson }
21807ec8bab3SRichard Henderson 
21817ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
21827ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
21837ec8bab3SRichard Henderson {
21847ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
21857ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
21867ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
21877ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
21887ec8bab3SRichard Henderson 
21897ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
21907ec8bab3SRichard Henderson     if (ofs + len == 64) {
21917ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
21927ec8bab3SRichard Henderson         return;
21937ec8bab3SRichard Henderson     }
21947ec8bab3SRichard Henderson     if (ofs == 0) {
21957ec8bab3SRichard Henderson         switch (len) {
21967ec8bab3SRichard Henderson         case 32:
21977ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
21987ec8bab3SRichard Henderson             return;
21997ec8bab3SRichard Henderson         case 16:
22007ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22017ec8bab3SRichard Henderson             return;
22027ec8bab3SRichard Henderson         case 8:
22037ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22047ec8bab3SRichard Henderson             return;
22057ec8bab3SRichard Henderson         }
22067ec8bab3SRichard Henderson     }
22077ec8bab3SRichard Henderson 
22087ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22097ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22107ec8bab3SRichard Henderson         if (ofs >= 32) {
22117ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22127ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
22137ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22147ec8bab3SRichard Henderson         } else if (ofs == 0) {
22157ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
22167ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
22177ec8bab3SRichard Henderson             return;
22187ec8bab3SRichard Henderson         } else if (len > 32) {
22197ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
22207ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
22217ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
22227ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
22237ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22247ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
22257ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
22267ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
22277ec8bab3SRichard Henderson             return;
22287ec8bab3SRichard Henderson         } else {
22297ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
22307ec8bab3SRichard Henderson                field sits at the MSB.  */
22317ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
22327ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
22337ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
22347ec8bab3SRichard Henderson         }
22357ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
22367ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
22377ec8bab3SRichard Henderson         return;
22387ec8bab3SRichard Henderson     }
22397ec8bab3SRichard Henderson 
22407ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
22417ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22427ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
22437ec8bab3SRichard Henderson         return;
22447ec8bab3SRichard Henderson     }
22457ec8bab3SRichard Henderson 
22467ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
22477ec8bab3SRichard Henderson     switch (ofs + len) {
22487ec8bab3SRichard Henderson     case 32:
22497ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
22507ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22517ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22527ec8bab3SRichard Henderson             return;
22537ec8bab3SRichard Henderson         }
22547ec8bab3SRichard Henderson         break;
22557ec8bab3SRichard Henderson     case 16:
22567ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
22577ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22587ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22597ec8bab3SRichard Henderson             return;
22607ec8bab3SRichard Henderson         }
22617ec8bab3SRichard Henderson         break;
22627ec8bab3SRichard Henderson     case 8:
22637ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
22647ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22657ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22667ec8bab3SRichard Henderson             return;
22677ec8bab3SRichard Henderson         }
22687ec8bab3SRichard Henderson         break;
22697ec8bab3SRichard Henderson     }
22707ec8bab3SRichard Henderson     switch (len) {
22717ec8bab3SRichard Henderson     case 32:
22727ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
22737ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22747ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
22757ec8bab3SRichard Henderson             return;
22767ec8bab3SRichard Henderson         }
22777ec8bab3SRichard Henderson         break;
22787ec8bab3SRichard Henderson     case 16:
22797ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
22807ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22817ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
22827ec8bab3SRichard Henderson             return;
22837ec8bab3SRichard Henderson         }
22847ec8bab3SRichard Henderson         break;
22857ec8bab3SRichard Henderson     case 8:
22867ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
22877ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22887ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
22897ec8bab3SRichard Henderson             return;
22907ec8bab3SRichard Henderson         }
22917ec8bab3SRichard Henderson         break;
22927ec8bab3SRichard Henderson     }
22937ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
22947ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
22957ec8bab3SRichard Henderson }
22967ec8bab3SRichard Henderson 
2297951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2298951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2299951c6300SRichard Henderson {
230037ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
230137ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
230237ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
230337ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
230437ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2305951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2306951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2307951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2308951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2309951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2310951c6300SRichard Henderson 
2311951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2312951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2313951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2314951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2315951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2316951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2317951c6300SRichard Henderson         } else {
2318951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2319951c6300SRichard Henderson 
2320951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2321951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2322951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2323951c6300SRichard Henderson 
2324951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2325951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2326951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2327951c6300SRichard Henderson         }
2328951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2329951c6300SRichard Henderson         tcg_temp_free_i32(t1);
23303a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2331951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2332951c6300SRichard Henderson     } else {
2333951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2334951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2335951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2336951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2337951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2338951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2339951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2340951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2341951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2342951c6300SRichard Henderson     }
2343951c6300SRichard Henderson }
2344951c6300SRichard Henderson 
2345951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2346951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2347951c6300SRichard Henderson {
2348951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2349951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2350951c6300SRichard Henderson     } else {
2351951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2352951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2353951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2354951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2355951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2356951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2357951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2358951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2359951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2360951c6300SRichard Henderson     }
2361951c6300SRichard Henderson }
2362951c6300SRichard Henderson 
2363951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2364951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2365951c6300SRichard Henderson {
2366951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2367951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2368951c6300SRichard Henderson     } else {
2369951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2370951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2371951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2372951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2373951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2374951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2375951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2376951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2377951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2378951c6300SRichard Henderson     }
2379951c6300SRichard Henderson }
2380951c6300SRichard Henderson 
2381951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2382951c6300SRichard Henderson {
2383951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2384951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2385951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2386951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2387951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2388951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2389951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2390951c6300SRichard Henderson         tcg_temp_free_i64(t);
2391951c6300SRichard Henderson     } else {
2392951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2393951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2394951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2395951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2396951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2397951c6300SRichard Henderson     }
2398951c6300SRichard Henderson }
2399951c6300SRichard Henderson 
2400951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2401951c6300SRichard Henderson {
2402951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2403951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2404951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2405951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2406951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2407951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2408951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2409951c6300SRichard Henderson         tcg_temp_free_i64(t);
2410951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2411951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2412951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2413951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2414951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2415951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2416951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2417951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2418951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2419951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2420951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2421951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2422951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2423951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2424951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2425951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2426951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2427951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2428951c6300SRichard Henderson     } else {
2429951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2430951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2431951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2432951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2433951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2434951c6300SRichard Henderson     }
2435951c6300SRichard Henderson }
2436951c6300SRichard Henderson 
24375087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
24385087abfbSRichard Henderson {
24395087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
24405087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
24415087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
24425087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
24435087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
24445087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
24455087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
24465087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
24475087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
24485087abfbSRichard Henderson     tcg_temp_free_i64(t0);
24495087abfbSRichard Henderson     tcg_temp_free_i64(t1);
24505087abfbSRichard Henderson     tcg_temp_free_i64(t2);
24515087abfbSRichard Henderson }
24525087abfbSRichard Henderson 
2453951c6300SRichard Henderson /* Size changing operations.  */
2454951c6300SRichard Henderson 
2455609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2456951c6300SRichard Henderson {
24573a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2458951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2459609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2460b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrl_i64_i32,
2461ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2462951c6300SRichard Henderson     } else {
2463dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)arg);
2464609ad705SRichard Henderson     }
2465609ad705SRichard Henderson }
2466609ad705SRichard Henderson 
2467609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2468609ad705SRichard Henderson {
2469609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2470609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2471609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2472b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extrh_i64_i32,
2473ae8b75dcSRichard Henderson                     tcgv_i32_arg(ret), tcgv_i64_arg(arg));
2474951c6300SRichard Henderson     } else {
2475951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2476609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2477dc41aa7dSRichard Henderson         tcg_gen_mov_i32(ret, (TCGv_i32)t);
2478951c6300SRichard Henderson         tcg_temp_free_i64(t);
2479951c6300SRichard Henderson     }
2480951c6300SRichard Henderson }
2481951c6300SRichard Henderson 
2482951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2483951c6300SRichard Henderson {
24843a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2485951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2486951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
24873a13c3f3SRichard Henderson     } else {
2488b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_extu_i32_i64,
2489ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
24903a13c3f3SRichard Henderson     }
2491951c6300SRichard Henderson }
2492951c6300SRichard Henderson 
2493951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2494951c6300SRichard Henderson {
24953a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2496951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2497951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
24983a13c3f3SRichard Henderson     } else {
2499b7e8b17aSRichard Henderson         tcg_gen_op2(INDEX_op_ext_i32_i64,
2500ae8b75dcSRichard Henderson                     tcgv_i64_arg(ret), tcgv_i32_arg(arg));
25013a13c3f3SRichard Henderson     }
2502951c6300SRichard Henderson }
2503951c6300SRichard Henderson 
2504951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2505951c6300SRichard Henderson {
25063a13c3f3SRichard Henderson     TCGv_i64 tmp;
25073a13c3f3SRichard Henderson 
25083a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2509951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2510951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
25113a13c3f3SRichard Henderson         return;
25123a13c3f3SRichard Henderson     }
25133a13c3f3SRichard Henderson 
25143a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2515951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2516951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2517951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2518951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2519951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2520951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2521951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2522951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2523951c6300SRichard Henderson     } else {
2524951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2525951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2526951c6300SRichard Henderson     }
2527951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2528951c6300SRichard Henderson }
2529951c6300SRichard Henderson 
2530951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2531951c6300SRichard Henderson {
25323a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2533951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2534951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
25353a13c3f3SRichard Henderson     } else {
2536609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2537609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
25383a13c3f3SRichard Henderson     }
2539951c6300SRichard Henderson }
2540951c6300SRichard Henderson 
2541951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2542951c6300SRichard Henderson {
2543951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2544951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2545951c6300SRichard Henderson }
2546951c6300SRichard Henderson 
2547951c6300SRichard Henderson /* QEMU specific operations.  */
2548951c6300SRichard Henderson 
2549951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2550951c6300SRichard Henderson {
2551951c6300SRichard Henderson     /* We only support two chained exits.  */
2552951c6300SRichard Henderson     tcg_debug_assert(idx <= 1);
2553951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2554951c6300SRichard Henderson     /* Verify that we havn't seen this numbered exit before.  */
2555*b1311c4aSEmilio G. Cota     tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
2556*b1311c4aSEmilio G. Cota     tcg_ctx->goto_tb_issue_mask |= 1 << idx;
2557951c6300SRichard Henderson #endif
2558951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2559951c6300SRichard Henderson }
2560951c6300SRichard Henderson 
25617f11636dSEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(void)
2562cedbcb01SEmilio G. Cota {
2563cedbcb01SEmilio G. Cota     if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
2564cedbcb01SEmilio G. Cota         TCGv_ptr ptr = tcg_temp_new_ptr();
2565*b1311c4aSEmilio G. Cota         gen_helper_lookup_tb_ptr(ptr, tcg_ctx->tcg_env);
2566ae8b75dcSRichard Henderson         tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
2567cedbcb01SEmilio G. Cota         tcg_temp_free_ptr(ptr);
2568cedbcb01SEmilio G. Cota     } else {
2569cedbcb01SEmilio G. Cota         tcg_gen_exit_tb(0);
2570cedbcb01SEmilio G. Cota     }
2571cedbcb01SEmilio G. Cota }
2572cedbcb01SEmilio G. Cota 
2573951c6300SRichard Henderson static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
2574951c6300SRichard Henderson {
25751f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
25761f00b27fSSergey Sorokin     (void)get_alignment_bits(op);
25771f00b27fSSergey Sorokin 
2578951c6300SRichard Henderson     switch (op & MO_SIZE) {
2579951c6300SRichard Henderson     case MO_8:
2580951c6300SRichard Henderson         op &= ~MO_BSWAP;
2581951c6300SRichard Henderson         break;
2582951c6300SRichard Henderson     case MO_16:
2583951c6300SRichard Henderson         break;
2584951c6300SRichard Henderson     case MO_32:
2585951c6300SRichard Henderson         if (!is64) {
2586951c6300SRichard Henderson             op &= ~MO_SIGN;
2587951c6300SRichard Henderson         }
2588951c6300SRichard Henderson         break;
2589951c6300SRichard Henderson     case MO_64:
2590951c6300SRichard Henderson         if (!is64) {
2591951c6300SRichard Henderson             tcg_abort();
2592951c6300SRichard Henderson         }
2593951c6300SRichard Henderson         break;
2594951c6300SRichard Henderson     }
2595951c6300SRichard Henderson     if (st) {
2596951c6300SRichard Henderson         op &= ~MO_SIGN;
2597951c6300SRichard Henderson     }
2598951c6300SRichard Henderson     return op;
2599951c6300SRichard Henderson }
2600951c6300SRichard Henderson 
2601c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
2602c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
2603951c6300SRichard Henderson {
260459227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2605951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
260659227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2607951c6300SRichard Henderson #else
2608c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
260959227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2610c45cb8bbSRichard Henderson     } else {
2611ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2612c45cb8bbSRichard Henderson     }
2613951c6300SRichard Henderson #endif
2614c45cb8bbSRichard Henderson }
2615c45cb8bbSRichard Henderson 
2616c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
2617c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
2618c45cb8bbSRichard Henderson {
261959227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2620c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2621c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
262259227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2623c45cb8bbSRichard Henderson     } else {
2624ae8b75dcSRichard Henderson         tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2625c45cb8bbSRichard Henderson     }
2626c45cb8bbSRichard Henderson #else
2627c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
262859227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
262959227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2630c45cb8bbSRichard Henderson     } else {
263159227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2632c45cb8bbSRichard Henderson     }
2633c45cb8bbSRichard Henderson #endif
2634c45cb8bbSRichard Henderson }
2635951c6300SRichard Henderson 
2636b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2637b32dc337SPranith Kumar {
2638b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2639b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2640b32dc337SPranith Kumar #endif
2641b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2642b32dc337SPranith Kumar     if (type) {
2643b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2644b32dc337SPranith Kumar     }
2645b32dc337SPranith Kumar }
2646b32dc337SPranith Kumar 
2647951c6300SRichard Henderson void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2648951c6300SRichard Henderson {
2649b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2650951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2651*b1311c4aSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, tcg_ctx->tcg_env,
2652dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
2653c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
2654951c6300SRichard Henderson }
2655951c6300SRichard Henderson 
2656951c6300SRichard Henderson void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2657951c6300SRichard Henderson {
2658b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2659951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
2660*b1311c4aSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, tcg_ctx->tcg_env,
2661dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
2662c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
2663951c6300SRichard Henderson }
2664951c6300SRichard Henderson 
2665951c6300SRichard Henderson void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2666951c6300SRichard Henderson {
2667b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
26683a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2669951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
2670951c6300SRichard Henderson         if (memop & MO_SIGN) {
2671951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
2672951c6300SRichard Henderson         } else {
2673951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
2674951c6300SRichard Henderson         }
2675951c6300SRichard Henderson         return;
2676951c6300SRichard Henderson     }
2677951c6300SRichard Henderson 
2678c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2679*b1311c4aSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, tcg_ctx->tcg_env,
2680dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
2681c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
2682951c6300SRichard Henderson }
2683951c6300SRichard Henderson 
2684951c6300SRichard Henderson void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2685951c6300SRichard Henderson {
2686b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
26873a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2688951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
2689951c6300SRichard Henderson         return;
2690951c6300SRichard Henderson     }
2691951c6300SRichard Henderson 
2692c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
2693*b1311c4aSEmilio G. Cota     trace_guest_mem_before_tcg(tcg_ctx->cpu, tcg_ctx->tcg_env,
2694dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
2695c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
2696951c6300SRichard Henderson }
2697c482cb11SRichard Henderson 
2698c482cb11SRichard Henderson static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc)
2699c482cb11SRichard Henderson {
2700c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2701c482cb11SRichard Henderson     case MO_SB:
2702c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
2703c482cb11SRichard Henderson         break;
2704c482cb11SRichard Henderson     case MO_UB:
2705c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
2706c482cb11SRichard Henderson         break;
2707c482cb11SRichard Henderson     case MO_SW:
2708c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
2709c482cb11SRichard Henderson         break;
2710c482cb11SRichard Henderson     case MO_UW:
2711c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
2712c482cb11SRichard Henderson         break;
2713c482cb11SRichard Henderson     default:
2714c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
2715c482cb11SRichard Henderson         break;
2716c482cb11SRichard Henderson     }
2717c482cb11SRichard Henderson }
2718c482cb11SRichard Henderson 
2719c482cb11SRichard Henderson static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, TCGMemOp opc)
2720c482cb11SRichard Henderson {
2721c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2722c482cb11SRichard Henderson     case MO_SB:
2723c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
2724c482cb11SRichard Henderson         break;
2725c482cb11SRichard Henderson     case MO_UB:
2726c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
2727c482cb11SRichard Henderson         break;
2728c482cb11SRichard Henderson     case MO_SW:
2729c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
2730c482cb11SRichard Henderson         break;
2731c482cb11SRichard Henderson     case MO_UW:
2732c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
2733c482cb11SRichard Henderson         break;
2734c482cb11SRichard Henderson     case MO_SL:
2735c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
2736c482cb11SRichard Henderson         break;
2737c482cb11SRichard Henderson     case MO_UL:
2738c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
2739c482cb11SRichard Henderson         break;
2740c482cb11SRichard Henderson     default:
2741c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
2742c482cb11SRichard Henderson         break;
2743c482cb11SRichard Henderson     }
2744c482cb11SRichard Henderson }
2745c482cb11SRichard Henderson 
2746c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2747c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
2748c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
2749c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
2750c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
2751c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
2752c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
2753c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
2754c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
2755c482cb11SRichard Henderson #else
2756c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
2757c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
2758c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
2759c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
2760c482cb11SRichard Henderson #endif
2761c482cb11SRichard Henderson 
2762df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2763df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
2764df79b996SRichard Henderson #else
2765df79b996SRichard Henderson # define WITH_ATOMIC64(X)
2766df79b996SRichard Henderson #endif
2767df79b996SRichard Henderson 
2768c482cb11SRichard Henderson static void * const table_cmpxchg[16] = {
2769c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
2770c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
2771c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
2772c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
2773c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
2774df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
2775df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
2776c482cb11SRichard Henderson };
2777c482cb11SRichard Henderson 
2778c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
2779c482cb11SRichard Henderson                                 TCGv_i32 newv, TCGArg idx, TCGMemOp memop)
2780c482cb11SRichard Henderson {
2781c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2782c482cb11SRichard Henderson 
2783*b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
2784c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2785c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
2786c482cb11SRichard Henderson 
2787c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
2788c482cb11SRichard Henderson 
2789c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2790c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
2791c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2792c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
2793c482cb11SRichard Henderson 
2794c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2795c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
2796c482cb11SRichard Henderson         } else {
2797c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
2798c482cb11SRichard Henderson         }
2799c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
2800c482cb11SRichard Henderson     } else {
2801c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
2802c482cb11SRichard Henderson 
2803c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2804c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2805c482cb11SRichard Henderson 
2806c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2807c482cb11SRichard Henderson         {
2808c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2809*b1311c4aSEmilio G. Cota             gen(retv, tcg_ctx->tcg_env, addr, cmpv, newv, oi);
2810c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2811c482cb11SRichard Henderson         }
2812c482cb11SRichard Henderson #else
2813*b1311c4aSEmilio G. Cota         gen(retv, tcg_ctx->tcg_env, addr, cmpv, newv);
2814c482cb11SRichard Henderson #endif
2815c482cb11SRichard Henderson 
2816c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2817c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
2818c482cb11SRichard Henderson         }
2819c482cb11SRichard Henderson     }
2820c482cb11SRichard Henderson }
2821c482cb11SRichard Henderson 
2822c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
2823c482cb11SRichard Henderson                                 TCGv_i64 newv, TCGArg idx, TCGMemOp memop)
2824c482cb11SRichard Henderson {
2825c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2826c482cb11SRichard Henderson 
2827*b1311c4aSEmilio G. Cota     if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
2828c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2829c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2830c482cb11SRichard Henderson 
2831c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
2832c482cb11SRichard Henderson 
2833c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2834c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
2835c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2836c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
2837c482cb11SRichard Henderson 
2838c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2839c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
2840c482cb11SRichard Henderson         } else {
2841c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
2842c482cb11SRichard Henderson         }
2843c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
2844c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
2845df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2846c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
2847c482cb11SRichard Henderson 
2848c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2849c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2850c482cb11SRichard Henderson 
2851c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2852c482cb11SRichard Henderson         {
2853c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
2854*b1311c4aSEmilio G. Cota             gen(retv, tcg_ctx->tcg_env, addr, cmpv, newv, oi);
2855c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2856c482cb11SRichard Henderson         }
2857c482cb11SRichard Henderson #else
2858*b1311c4aSEmilio G. Cota         gen(retv, tcg_ctx->tcg_env, addr, cmpv, newv);
2859c482cb11SRichard Henderson #endif
2860df79b996SRichard Henderson #else
2861*b1311c4aSEmilio G. Cota         gen_helper_exit_atomic(tcg_ctx->tcg_env);
286279b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
286379b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
286479b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
2865df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
2866c482cb11SRichard Henderson     } else {
2867c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
2868c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
2869c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
2870c482cb11SRichard Henderson 
2871c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
2872c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
2873c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
2874c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
2875c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
2876c482cb11SRichard Henderson 
2877c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
2878c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
2879c482cb11SRichard Henderson 
2880c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2881c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
2882c482cb11SRichard Henderson         }
2883c482cb11SRichard Henderson     }
2884c482cb11SRichard Henderson }
2885c482cb11SRichard Henderson 
2886c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2887c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2888c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
2889c482cb11SRichard Henderson {
2890c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
2891c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
2892c482cb11SRichard Henderson 
2893c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2894c482cb11SRichard Henderson 
2895c482cb11SRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2896c482cb11SRichard Henderson     gen(t2, t1, val);
2897c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2898c482cb11SRichard Henderson 
2899c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
2900c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
2901c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
2902c482cb11SRichard Henderson }
2903c482cb11SRichard Henderson 
2904c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2905c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2906c482cb11SRichard Henderson {
2907c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
2908c482cb11SRichard Henderson 
2909c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2910c482cb11SRichard Henderson 
2911c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
2912c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
2913c482cb11SRichard Henderson 
2914c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2915c482cb11SRichard Henderson     {
2916c482cb11SRichard Henderson         TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2917*b1311c4aSEmilio G. Cota         gen(ret, tcg_ctx->tcg_env, addr, val, oi);
2918c482cb11SRichard Henderson         tcg_temp_free_i32(oi);
2919c482cb11SRichard Henderson     }
2920c482cb11SRichard Henderson #else
2921*b1311c4aSEmilio G. Cota     gen(ret, tcg_ctx->tcg_env, addr, val);
2922c482cb11SRichard Henderson #endif
2923c482cb11SRichard Henderson 
2924c482cb11SRichard Henderson     if (memop & MO_SIGN) {
2925c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
2926c482cb11SRichard Henderson     }
2927c482cb11SRichard Henderson }
2928c482cb11SRichard Henderson 
2929c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2930c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2931c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
2932c482cb11SRichard Henderson {
2933c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
2934c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
2935c482cb11SRichard Henderson 
2936c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2937c482cb11SRichard Henderson 
2938c482cb11SRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2939c482cb11SRichard Henderson     gen(t2, t1, val);
2940c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2941c482cb11SRichard Henderson 
2942c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
2943c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
2944c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
2945c482cb11SRichard Henderson }
2946c482cb11SRichard Henderson 
2947c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2948c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2949c482cb11SRichard Henderson {
2950c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2951c482cb11SRichard Henderson 
2952c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
2953df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2954c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
2955c482cb11SRichard Henderson 
2956c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
2957c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2958c482cb11SRichard Henderson 
2959c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2960c482cb11SRichard Henderson         {
2961c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2962*b1311c4aSEmilio G. Cota             gen(ret, tcg_ctx->tcg_env, addr, val, oi);
2963c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2964c482cb11SRichard Henderson         }
2965c482cb11SRichard Henderson #else
2966*b1311c4aSEmilio G. Cota         gen(ret, tcg_ctx->tcg_env, addr, val);
2967c482cb11SRichard Henderson #endif
2968df79b996SRichard Henderson #else
2969*b1311c4aSEmilio G. Cota         gen_helper_exit_atomic(tcg_ctx->tcg_env);
297079b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
297179b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
297279b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
2973df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
2974c482cb11SRichard Henderson     } else {
2975c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
2976c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
2977c482cb11SRichard Henderson 
2978c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
2979c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
2980c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
2981c482cb11SRichard Henderson 
2982c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
2983c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
2984c482cb11SRichard Henderson 
2985c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2986c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
2987c482cb11SRichard Henderson         }
2988c482cb11SRichard Henderson     }
2989c482cb11SRichard Henderson }
2990c482cb11SRichard Henderson 
2991c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
2992c482cb11SRichard Henderson static void * const table_##NAME[16] = {                                \
2993c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
2994c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
2995c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
2996c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
2997c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
2998df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
2999df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3000c482cb11SRichard Henderson };                                                                      \
3001c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
3002c482cb11SRichard Henderson     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \
3003c482cb11SRichard Henderson {                                                                       \
3004*b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3005c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3006c482cb11SRichard Henderson     } else {                                                            \
3007c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3008c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3009c482cb11SRichard Henderson     }                                                                   \
3010c482cb11SRichard Henderson }                                                                       \
3011c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
3012c482cb11SRichard Henderson     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \
3013c482cb11SRichard Henderson {                                                                       \
3014*b1311c4aSEmilio G. Cota     if (tcg_ctx->tb_cflags & CF_PARALLEL) {                             \
3015c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3016c482cb11SRichard Henderson     } else {                                                            \
3017c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3018c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3019c482cb11SRichard Henderson     }                                                                   \
3020c482cb11SRichard Henderson }
3021c482cb11SRichard Henderson 
3022c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3023c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3024c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3025c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
3026c482cb11SRichard Henderson 
3027c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3028c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3029c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3030c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
3031c482cb11SRichard Henderson 
3032c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3033c482cb11SRichard Henderson {
3034c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3035c482cb11SRichard Henderson }
3036c482cb11SRichard Henderson 
3037c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3038c482cb11SRichard Henderson {
3039c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3040c482cb11SRichard Henderson }
3041c482cb11SRichard Henderson 
3042c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3043c482cb11SRichard Henderson 
3044c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3045