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