xref: /openbmc/qemu/tcg/tcg-op.c (revision b32dc337)
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"
31*b32dc337SPranith 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 
49c45cb8bbSRichard Henderson static void tcg_emit_op(TCGContext *ctx, TCGOpcode opc, int args)
50c45cb8bbSRichard Henderson {
51c45cb8bbSRichard Henderson     int oi = ctx->gen_next_op_idx;
52c45cb8bbSRichard Henderson     int ni = oi + 1;
53c45cb8bbSRichard Henderson     int pi = oi - 1;
54c45cb8bbSRichard Henderson 
55c45cb8bbSRichard Henderson     tcg_debug_assert(oi < OPC_BUF_SIZE);
56dcb8e758SRichard Henderson     ctx->gen_op_buf[0].prev = oi;
57c45cb8bbSRichard Henderson     ctx->gen_next_op_idx = ni;
58c45cb8bbSRichard Henderson 
59c45cb8bbSRichard Henderson     ctx->gen_op_buf[oi] = (TCGOp){
60c45cb8bbSRichard Henderson         .opc = opc,
61c45cb8bbSRichard Henderson         .args = args,
62c45cb8bbSRichard Henderson         .prev = pi,
63c45cb8bbSRichard Henderson         .next = ni
64c45cb8bbSRichard Henderson     };
65c45cb8bbSRichard Henderson }
66c45cb8bbSRichard Henderson 
67951c6300SRichard Henderson void tcg_gen_op1(TCGContext *ctx, TCGOpcode opc, TCGArg a1)
68951c6300SRichard Henderson {
69c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
70951c6300SRichard Henderson 
71c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 1 <= OPPARAM_BUF_SIZE);
72c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 1;
73c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi] = a1;
74951c6300SRichard Henderson 
75c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
76951c6300SRichard Henderson }
77951c6300SRichard Henderson 
78951c6300SRichard Henderson void tcg_gen_op2(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2)
79951c6300SRichard Henderson {
80c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
81951c6300SRichard Henderson 
82c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 2 <= OPPARAM_BUF_SIZE);
83c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 2;
84c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
85c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
86951c6300SRichard Henderson 
87c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
88951c6300SRichard Henderson }
89951c6300SRichard Henderson 
90951c6300SRichard Henderson void tcg_gen_op3(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
91951c6300SRichard Henderson                  TCGArg a2, TCGArg a3)
92951c6300SRichard Henderson {
93c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
94951c6300SRichard Henderson 
95c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 3 <= OPPARAM_BUF_SIZE);
96c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 3;
97c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
98c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
99c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
100951c6300SRichard Henderson 
101c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
102951c6300SRichard Henderson }
103951c6300SRichard Henderson 
104951c6300SRichard Henderson void tcg_gen_op4(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
105951c6300SRichard Henderson                  TCGArg a2, TCGArg a3, TCGArg a4)
106951c6300SRichard Henderson {
107c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
108951c6300SRichard Henderson 
109c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 4 <= OPPARAM_BUF_SIZE);
110c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 4;
111c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
112c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
113c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
114c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 3] = a4;
115951c6300SRichard Henderson 
116c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
117951c6300SRichard Henderson }
118951c6300SRichard Henderson 
119951c6300SRichard Henderson void tcg_gen_op5(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
120951c6300SRichard Henderson                  TCGArg a2, TCGArg a3, TCGArg a4, TCGArg a5)
121951c6300SRichard Henderson {
122c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
123951c6300SRichard Henderson 
124c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 5 <= OPPARAM_BUF_SIZE);
125c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 5;
126c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
127c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
128c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
129c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 3] = a4;
130c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 4] = a5;
131951c6300SRichard Henderson 
132c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
133951c6300SRichard Henderson }
134951c6300SRichard Henderson 
135951c6300SRichard Henderson void tcg_gen_op6(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2,
136951c6300SRichard Henderson                  TCGArg a3, TCGArg a4, TCGArg a5, TCGArg a6)
137951c6300SRichard Henderson {
138c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
139951c6300SRichard Henderson 
140c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 6 <= OPPARAM_BUF_SIZE);
141c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 6;
142c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
143c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
144c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
145c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 3] = a4;
146c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 4] = a5;
147c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 5] = a6;
148951c6300SRichard Henderson 
149c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
150951c6300SRichard Henderson }
151951c6300SRichard Henderson 
152f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
153f65e19bcSPranith Kumar {
15491682118SRichard Henderson     if (parallel_cpus) {
155f65e19bcSPranith Kumar         tcg_gen_op1(&tcg_ctx, INDEX_op_mb, mb_type);
156f65e19bcSPranith Kumar     }
157f65e19bcSPranith Kumar }
158f65e19bcSPranith Kumar 
159951c6300SRichard Henderson /* 32 bit ops */
160951c6300SRichard Henderson 
161951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
162951c6300SRichard Henderson {
163951c6300SRichard Henderson     /* some cases can be optimized here */
164951c6300SRichard Henderson     if (arg2 == 0) {
165951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
166951c6300SRichard Henderson     } else {
167951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
168951c6300SRichard Henderson         tcg_gen_add_i32(ret, arg1, t0);
169951c6300SRichard Henderson         tcg_temp_free_i32(t0);
170951c6300SRichard Henderson     }
171951c6300SRichard Henderson }
172951c6300SRichard Henderson 
173951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
174951c6300SRichard Henderson {
175951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
176951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
177951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
178951c6300SRichard Henderson     } else {
179951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg1);
180951c6300SRichard Henderson         tcg_gen_sub_i32(ret, t0, arg2);
181951c6300SRichard Henderson         tcg_temp_free_i32(t0);
182951c6300SRichard Henderson     }
183951c6300SRichard Henderson }
184951c6300SRichard Henderson 
185951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
186951c6300SRichard Henderson {
187951c6300SRichard Henderson     /* some cases can be optimized here */
188951c6300SRichard Henderson     if (arg2 == 0) {
189951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
190951c6300SRichard Henderson     } else {
191951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
192951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
193951c6300SRichard Henderson         tcg_temp_free_i32(t0);
194951c6300SRichard Henderson     }
195951c6300SRichard Henderson }
196951c6300SRichard Henderson 
197951c6300SRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
198951c6300SRichard Henderson {
199951c6300SRichard Henderson     TCGv_i32 t0;
200951c6300SRichard Henderson     /* Some cases can be optimized here.  */
201951c6300SRichard Henderson     switch (arg2) {
202951c6300SRichard Henderson     case 0:
203951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
204951c6300SRichard Henderson         return;
205951c6300SRichard Henderson     case 0xffffffffu:
206951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
207951c6300SRichard Henderson         return;
208951c6300SRichard Henderson     case 0xffu:
209951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
210951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
211951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
212951c6300SRichard Henderson             return;
213951c6300SRichard Henderson         }
214951c6300SRichard Henderson         break;
215951c6300SRichard Henderson     case 0xffffu:
216951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
217951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
218951c6300SRichard Henderson             return;
219951c6300SRichard Henderson         }
220951c6300SRichard Henderson         break;
221951c6300SRichard Henderson     }
222951c6300SRichard Henderson     t0 = tcg_const_i32(arg2);
223951c6300SRichard Henderson     tcg_gen_and_i32(ret, arg1, t0);
224951c6300SRichard Henderson     tcg_temp_free_i32(t0);
225951c6300SRichard Henderson }
226951c6300SRichard Henderson 
227951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
228951c6300SRichard Henderson {
229951c6300SRichard Henderson     /* Some cases can be optimized here.  */
230951c6300SRichard Henderson     if (arg2 == -1) {
231951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
232951c6300SRichard Henderson     } else if (arg2 == 0) {
233951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
234951c6300SRichard Henderson     } else {
235951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
236951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
237951c6300SRichard Henderson         tcg_temp_free_i32(t0);
238951c6300SRichard Henderson     }
239951c6300SRichard Henderson }
240951c6300SRichard Henderson 
241951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
242951c6300SRichard Henderson {
243951c6300SRichard Henderson     /* Some cases can be optimized here.  */
244951c6300SRichard Henderson     if (arg2 == 0) {
245951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
246951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
247951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
248951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
249951c6300SRichard Henderson     } else {
250951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
251951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, t0);
252951c6300SRichard Henderson         tcg_temp_free_i32(t0);
253951c6300SRichard Henderson     }
254951c6300SRichard Henderson }
255951c6300SRichard Henderson 
256951c6300SRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
257951c6300SRichard Henderson {
258951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
259951c6300SRichard Henderson     if (arg2 == 0) {
260951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
261951c6300SRichard Henderson     } else {
262951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
263951c6300SRichard Henderson         tcg_gen_shl_i32(ret, arg1, t0);
264951c6300SRichard Henderson         tcg_temp_free_i32(t0);
265951c6300SRichard Henderson     }
266951c6300SRichard Henderson }
267951c6300SRichard Henderson 
268951c6300SRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
269951c6300SRichard Henderson {
270951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
271951c6300SRichard Henderson     if (arg2 == 0) {
272951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
273951c6300SRichard Henderson     } else {
274951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
275951c6300SRichard Henderson         tcg_gen_shr_i32(ret, arg1, t0);
276951c6300SRichard Henderson         tcg_temp_free_i32(t0);
277951c6300SRichard Henderson     }
278951c6300SRichard Henderson }
279951c6300SRichard Henderson 
280951c6300SRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
281951c6300SRichard Henderson {
282951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
283951c6300SRichard Henderson     if (arg2 == 0) {
284951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
285951c6300SRichard Henderson     } else {
286951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
287951c6300SRichard Henderson         tcg_gen_sar_i32(ret, arg1, t0);
288951c6300SRichard Henderson         tcg_temp_free_i32(t0);
289951c6300SRichard Henderson     }
290951c6300SRichard Henderson }
291951c6300SRichard Henderson 
29242a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
293951c6300SRichard Henderson {
294951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
29542a268c2SRichard Henderson         tcg_gen_br(l);
296951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
29742a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
298951c6300SRichard Henderson     }
299951c6300SRichard Henderson }
300951c6300SRichard Henderson 
30142a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
302951c6300SRichard Henderson {
30337ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
30437ed3bf1SRichard Henderson         tcg_gen_br(l);
30537ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
306951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
30742a268c2SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, t0, l);
308951c6300SRichard Henderson         tcg_temp_free_i32(t0);
309951c6300SRichard Henderson     }
31037ed3bf1SRichard Henderson }
311951c6300SRichard Henderson 
312951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
313951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
314951c6300SRichard Henderson {
315951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
316951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
317951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
318951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
319951c6300SRichard Henderson     } else {
320951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
321951c6300SRichard Henderson     }
322951c6300SRichard Henderson }
323951c6300SRichard Henderson 
324951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
325951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
326951c6300SRichard Henderson {
327951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
328951c6300SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, t0);
329951c6300SRichard Henderson     tcg_temp_free_i32(t0);
330951c6300SRichard Henderson }
331951c6300SRichard Henderson 
332951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
333951c6300SRichard Henderson {
334951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
335951c6300SRichard Henderson     tcg_gen_mul_i32(ret, arg1, t0);
336951c6300SRichard Henderson     tcg_temp_free_i32(t0);
337951c6300SRichard Henderson }
338951c6300SRichard Henderson 
339951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
340951c6300SRichard Henderson {
341951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
342951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
343951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
344951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
345951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
346951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
347951c6300SRichard Henderson         tcg_temp_free_i32(t0);
348951c6300SRichard Henderson     } else {
349951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
350951c6300SRichard Henderson     }
351951c6300SRichard Henderson }
352951c6300SRichard Henderson 
353951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
354951c6300SRichard Henderson {
355951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
356951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
357951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
358951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
359951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
360951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
361951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
362951c6300SRichard Henderson         tcg_temp_free_i32(t0);
363951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
364951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
365951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
366951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
367951c6300SRichard Henderson         tcg_temp_free_i32(t0);
368951c6300SRichard Henderson     } else {
369951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
370951c6300SRichard Henderson     }
371951c6300SRichard Henderson }
372951c6300SRichard Henderson 
373951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
374951c6300SRichard Henderson {
375951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
376951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
377951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
378951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
379951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
380951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
381951c6300SRichard Henderson         tcg_temp_free_i32(t0);
382951c6300SRichard Henderson     } else {
383951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
384951c6300SRichard Henderson     }
385951c6300SRichard Henderson }
386951c6300SRichard Henderson 
387951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
388951c6300SRichard Henderson {
389951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
390951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
391951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
392951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
393951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
394951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
395951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
396951c6300SRichard Henderson         tcg_temp_free_i32(t0);
397951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
398951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
399951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
400951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
401951c6300SRichard Henderson         tcg_temp_free_i32(t0);
402951c6300SRichard Henderson     } else {
403951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
404951c6300SRichard Henderson     }
405951c6300SRichard Henderson }
406951c6300SRichard Henderson 
407951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
408951c6300SRichard Henderson {
409951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
410951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
411951c6300SRichard Henderson     } else {
412951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
413951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
414951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
415951c6300SRichard Henderson         tcg_temp_free_i32(t0);
416951c6300SRichard Henderson     }
417951c6300SRichard Henderson }
418951c6300SRichard Henderson 
419951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
420951c6300SRichard Henderson {
421951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
422951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
423951c6300SRichard Henderson     } else {
424951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
425951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
426951c6300SRichard Henderson     }
427951c6300SRichard Henderson }
428951c6300SRichard Henderson 
429951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
430951c6300SRichard Henderson {
431951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
432951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
433951c6300SRichard Henderson     } else {
434951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
435951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
436951c6300SRichard Henderson     }
437951c6300SRichard Henderson }
438951c6300SRichard Henderson 
439951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
440951c6300SRichard Henderson {
441951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
442951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
443951c6300SRichard Henderson     } else {
444951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
445951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
446951c6300SRichard Henderson     }
447951c6300SRichard Henderson }
448951c6300SRichard Henderson 
449951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
450951c6300SRichard Henderson {
451951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
452951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
453951c6300SRichard Henderson     } else {
454951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
455951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
456951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
457951c6300SRichard Henderson         tcg_temp_free_i32(t0);
458951c6300SRichard Henderson     }
459951c6300SRichard Henderson }
460951c6300SRichard Henderson 
4610e28d006SRichard Henderson void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4620e28d006SRichard Henderson {
4630e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
4640e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_clz_i32, ret, arg1, arg2);
4650e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_clz_i64) {
4660e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4670e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4680e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4690e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4700e28d006SRichard Henderson         tcg_gen_addi_i64(t2, t2, 32);
4710e28d006SRichard Henderson         tcg_gen_clz_i64(t1, t1, t2);
4720e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4730e28d006SRichard Henderson         tcg_temp_free_i64(t1);
4740e28d006SRichard Henderson         tcg_temp_free_i64(t2);
4750e28d006SRichard Henderson         tcg_gen_subi_i32(ret, ret, 32);
4760e28d006SRichard Henderson     } else {
4770e28d006SRichard Henderson         gen_helper_clz_i32(ret, arg1, arg2);
4780e28d006SRichard Henderson     }
4790e28d006SRichard Henderson }
4800e28d006SRichard Henderson 
4810e28d006SRichard Henderson void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
4820e28d006SRichard Henderson {
4830e28d006SRichard Henderson     TCGv_i32 t = tcg_const_i32(arg2);
4840e28d006SRichard Henderson     tcg_gen_clz_i32(ret, arg1, t);
4850e28d006SRichard Henderson     tcg_temp_free_i32(t);
4860e28d006SRichard Henderson }
4870e28d006SRichard Henderson 
4880e28d006SRichard Henderson void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
4890e28d006SRichard Henderson {
4900e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i32) {
4910e28d006SRichard Henderson         tcg_gen_op3_i32(INDEX_op_ctz_i32, ret, arg1, arg2);
4920e28d006SRichard Henderson     } else if (TCG_TARGET_HAS_ctz_i64) {
4930e28d006SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
4940e28d006SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
4950e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg1);
4960e28d006SRichard Henderson         tcg_gen_extu_i32_i64(t2, arg2);
4970e28d006SRichard Henderson         tcg_gen_ctz_i64(t1, t1, t2);
4980e28d006SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t1);
4990e28d006SRichard Henderson         tcg_temp_free_i64(t1);
5000e28d006SRichard Henderson         tcg_temp_free_i64(t2);
50114e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i32
50214e99210SRichard Henderson                || TCG_TARGET_HAS_ctpop_i64
50314e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i32
50414e99210SRichard Henderson                || TCG_TARGET_HAS_clz_i64) {
50514e99210SRichard Henderson         TCGv_i32 z, t = tcg_temp_new_i32();
50614e99210SRichard Henderson 
50714e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i32 || TCG_TARGET_HAS_ctpop_i64) {
50814e99210SRichard Henderson             tcg_gen_subi_i32(t, arg1, 1);
50914e99210SRichard Henderson             tcg_gen_andc_i32(t, t, arg1);
51014e99210SRichard Henderson             tcg_gen_ctpop_i32(t, t);
51114e99210SRichard Henderson         } else {
51214e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 32, don't fight it.  */
51314e99210SRichard Henderson             tcg_gen_neg_i32(t, arg1);
51414e99210SRichard Henderson             tcg_gen_and_i32(t, t, arg1);
51514e99210SRichard Henderson             tcg_gen_clzi_i32(t, t, 32);
51614e99210SRichard Henderson             tcg_gen_xori_i32(t, t, 31);
51714e99210SRichard Henderson         }
51814e99210SRichard Henderson         z = tcg_const_i32(0);
51914e99210SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
52014e99210SRichard Henderson         tcg_temp_free_i32(t);
52114e99210SRichard Henderson         tcg_temp_free_i32(z);
5220e28d006SRichard Henderson     } else {
5230e28d006SRichard Henderson         gen_helper_ctz_i32(ret, arg1, arg2);
5240e28d006SRichard Henderson     }
5250e28d006SRichard Henderson }
5260e28d006SRichard Henderson 
5270e28d006SRichard Henderson void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
5280e28d006SRichard Henderson {
52914e99210SRichard Henderson     if (!TCG_TARGET_HAS_ctz_i32 && TCG_TARGET_HAS_ctpop_i32 && arg2 == 32) {
53014e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
53114e99210SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
53214e99210SRichard Henderson         tcg_gen_subi_i32(t, arg1, 1);
53314e99210SRichard Henderson         tcg_gen_andc_i32(t, t, arg1);
53414e99210SRichard Henderson         tcg_gen_ctpop_i32(ret, t);
53514e99210SRichard Henderson         tcg_temp_free_i32(t);
53614e99210SRichard Henderson     } else {
5370e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32(arg2);
5380e28d006SRichard Henderson         tcg_gen_ctz_i32(ret, arg1, t);
5390e28d006SRichard Henderson         tcg_temp_free_i32(t);
5400e28d006SRichard Henderson     }
54114e99210SRichard Henderson }
5420e28d006SRichard Henderson 
543086920c2SRichard Henderson void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg)
544086920c2SRichard Henderson {
545086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i32) {
546086920c2SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
547086920c2SRichard Henderson         tcg_gen_sari_i32(t, arg, 31);
548086920c2SRichard Henderson         tcg_gen_xor_i32(t, t, arg);
549086920c2SRichard Henderson         tcg_gen_clzi_i32(t, t, 32);
550086920c2SRichard Henderson         tcg_gen_subi_i32(ret, t, 1);
551086920c2SRichard Henderson         tcg_temp_free_i32(t);
552086920c2SRichard Henderson     } else {
553086920c2SRichard Henderson         gen_helper_clrsb_i32(ret, arg);
554086920c2SRichard Henderson     }
555086920c2SRichard Henderson }
556086920c2SRichard Henderson 
557a768e4e9SRichard Henderson void tcg_gen_ctpop_i32(TCGv_i32 ret, TCGv_i32 arg1)
558a768e4e9SRichard Henderson {
559a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i32) {
560a768e4e9SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ctpop_i32, ret, arg1);
561a768e4e9SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64) {
562a768e4e9SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
563a768e4e9SRichard Henderson         tcg_gen_extu_i32_i64(t, arg1);
564a768e4e9SRichard Henderson         tcg_gen_ctpop_i64(t, t);
565a768e4e9SRichard Henderson         tcg_gen_extrl_i64_i32(ret, t);
566a768e4e9SRichard Henderson         tcg_temp_free_i64(t);
567a768e4e9SRichard Henderson     } else {
568a768e4e9SRichard Henderson         gen_helper_ctpop_i32(ret, arg1);
569a768e4e9SRichard Henderson     }
570a768e4e9SRichard Henderson }
571a768e4e9SRichard Henderson 
572951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
573951c6300SRichard Henderson {
574951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
575951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
576951c6300SRichard Henderson     } else {
577951c6300SRichard Henderson         TCGv_i32 t0, t1;
578951c6300SRichard Henderson 
579951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
580951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
581951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
582951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
583951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
584951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
585951c6300SRichard Henderson         tcg_temp_free_i32(t0);
586951c6300SRichard Henderson         tcg_temp_free_i32(t1);
587951c6300SRichard Henderson     }
588951c6300SRichard Henderson }
589951c6300SRichard Henderson 
590951c6300SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
591951c6300SRichard Henderson {
592951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
593951c6300SRichard Henderson     /* some cases can be optimized here */
594951c6300SRichard Henderson     if (arg2 == 0) {
595951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
596951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
597951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
598951c6300SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, t0);
599951c6300SRichard Henderson         tcg_temp_free_i32(t0);
600951c6300SRichard Henderson     } else {
601951c6300SRichard Henderson         TCGv_i32 t0, t1;
602951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
603951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
604951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
605951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
606951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
607951c6300SRichard Henderson         tcg_temp_free_i32(t0);
608951c6300SRichard Henderson         tcg_temp_free_i32(t1);
609951c6300SRichard Henderson     }
610951c6300SRichard Henderson }
611951c6300SRichard Henderson 
612951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
613951c6300SRichard Henderson {
614951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
615951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
616951c6300SRichard Henderson     } else {
617951c6300SRichard Henderson         TCGv_i32 t0, t1;
618951c6300SRichard Henderson 
619951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
620951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
621951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
622951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
623951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
624951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
625951c6300SRichard Henderson         tcg_temp_free_i32(t0);
626951c6300SRichard Henderson         tcg_temp_free_i32(t1);
627951c6300SRichard Henderson     }
628951c6300SRichard Henderson }
629951c6300SRichard Henderson 
630951c6300SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
631951c6300SRichard Henderson {
632951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
633951c6300SRichard Henderson     /* some cases can be optimized here */
634951c6300SRichard Henderson     if (arg2 == 0) {
635951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
636951c6300SRichard Henderson     } else {
637951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
638951c6300SRichard Henderson     }
639951c6300SRichard Henderson }
640951c6300SRichard Henderson 
641951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
642951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
643951c6300SRichard Henderson {
644951c6300SRichard Henderson     uint32_t mask;
645951c6300SRichard Henderson     TCGv_i32 t1;
646951c6300SRichard Henderson 
647951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
6480d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
649951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
650951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
651951c6300SRichard Henderson 
6520d0d309dSRichard Henderson     if (len == 32) {
653951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
654951c6300SRichard Henderson         return;
655951c6300SRichard Henderson     }
656951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
657951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
658951c6300SRichard Henderson         return;
659951c6300SRichard Henderson     }
660951c6300SRichard Henderson 
661951c6300SRichard Henderson     mask = (1u << len) - 1;
662951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
663951c6300SRichard Henderson 
664951c6300SRichard Henderson     if (ofs + len < 32) {
665951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
666951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
667951c6300SRichard Henderson     } else {
668951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
669951c6300SRichard Henderson     }
670951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
671951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
672951c6300SRichard Henderson 
673951c6300SRichard Henderson     tcg_temp_free_i32(t1);
674951c6300SRichard Henderson }
675951c6300SRichard Henderson 
67607cc68d5SRichard Henderson void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
67707cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
67807cc68d5SRichard Henderson {
67907cc68d5SRichard Henderson     tcg_debug_assert(ofs < 32);
68007cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
68107cc68d5SRichard Henderson     tcg_debug_assert(len <= 32);
68207cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
68307cc68d5SRichard Henderson 
68407cc68d5SRichard Henderson     if (ofs + len == 32) {
68507cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, arg, ofs);
68607cc68d5SRichard Henderson     } else if (ofs == 0) {
68707cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
68807cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i32
68907cc68d5SRichard Henderson                && TCG_TARGET_deposit_i32_valid(ofs, len)) {
69007cc68d5SRichard Henderson         TCGv_i32 zero = tcg_const_i32(0);
69107cc68d5SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
69207cc68d5SRichard Henderson         tcg_temp_free_i32(zero);
69307cc68d5SRichard Henderson     } else {
69407cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
69507cc68d5SRichard Henderson            which allows ARG to stay live.  */
69607cc68d5SRichard Henderson         switch (len) {
69707cc68d5SRichard Henderson         case 16:
69807cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
69907cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, arg);
70007cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
70107cc68d5SRichard Henderson                 return;
70207cc68d5SRichard Henderson             }
70307cc68d5SRichard Henderson             break;
70407cc68d5SRichard Henderson         case 8:
70507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
70607cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, arg);
70707cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, ret, ofs);
70807cc68d5SRichard Henderson                 return;
70907cc68d5SRichard Henderson             }
71007cc68d5SRichard Henderson             break;
71107cc68d5SRichard Henderson         }
71207cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
71307cc68d5SRichard Henderson         switch (ofs + len) {
71407cc68d5SRichard Henderson         case 16:
71507cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i32) {
71607cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
71707cc68d5SRichard Henderson                 tcg_gen_ext16u_i32(ret, ret);
71807cc68d5SRichard Henderson                 return;
71907cc68d5SRichard Henderson             }
72007cc68d5SRichard Henderson             break;
72107cc68d5SRichard Henderson         case 8:
72207cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i32) {
72307cc68d5SRichard Henderson                 tcg_gen_shli_i32(ret, arg, ofs);
72407cc68d5SRichard Henderson                 tcg_gen_ext8u_i32(ret, ret);
72507cc68d5SRichard Henderson                 return;
72607cc68d5SRichard Henderson             }
72707cc68d5SRichard Henderson             break;
72807cc68d5SRichard Henderson         }
72907cc68d5SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
73007cc68d5SRichard Henderson         tcg_gen_shli_i32(ret, ret, ofs);
73107cc68d5SRichard Henderson     }
73207cc68d5SRichard Henderson }
73307cc68d5SRichard Henderson 
7347ec8bab3SRichard Henderson void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
7357ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
7367ec8bab3SRichard Henderson {
7377ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7387ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7397ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7407ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7417ec8bab3SRichard Henderson 
7427ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
7437ec8bab3SRichard Henderson     if (ofs + len == 32) {
7447ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, 32 - len);
7457ec8bab3SRichard Henderson         return;
7467ec8bab3SRichard Henderson     }
7477ec8bab3SRichard Henderson     if (ofs == 0) {
7487ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
7497ec8bab3SRichard Henderson         return;
7507ec8bab3SRichard Henderson     }
7517ec8bab3SRichard Henderson 
7527ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i32
7537ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
7547ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len);
7557ec8bab3SRichard Henderson         return;
7567ec8bab3SRichard Henderson     }
7577ec8bab3SRichard Henderson 
7587ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
7597ec8bab3SRichard Henderson     switch (ofs + len) {
7607ec8bab3SRichard Henderson     case 16:
7617ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
7627ec8bab3SRichard Henderson             tcg_gen_ext16u_i32(ret, arg);
7637ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7647ec8bab3SRichard Henderson             return;
7657ec8bab3SRichard Henderson         }
7667ec8bab3SRichard Henderson         break;
7677ec8bab3SRichard Henderson     case 8:
7687ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
7697ec8bab3SRichard Henderson             tcg_gen_ext8u_i32(ret, arg);
7707ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, ret, ofs);
7717ec8bab3SRichard Henderson             return;
7727ec8bab3SRichard Henderson         }
7737ec8bab3SRichard Henderson         break;
7747ec8bab3SRichard Henderson     }
7757ec8bab3SRichard Henderson 
7767ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
7777ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special case of 16,
7787ec8bab3SRichard Henderson        so that we get ext8u, ext16u.  */
7797ec8bab3SRichard Henderson     switch (len) {
7807ec8bab3SRichard Henderson     case 1 ... 8: case 16:
7817ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, arg, ofs);
7827ec8bab3SRichard Henderson         tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
7837ec8bab3SRichard Henderson         break;
7847ec8bab3SRichard Henderson     default:
7857ec8bab3SRichard Henderson         tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
7867ec8bab3SRichard Henderson         tcg_gen_shri_i32(ret, ret, 32 - len);
7877ec8bab3SRichard Henderson         break;
7887ec8bab3SRichard Henderson     }
7897ec8bab3SRichard Henderson }
7907ec8bab3SRichard Henderson 
7917ec8bab3SRichard Henderson void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
7927ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
7937ec8bab3SRichard Henderson {
7947ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 32);
7957ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
7967ec8bab3SRichard Henderson     tcg_debug_assert(len <= 32);
7977ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
7987ec8bab3SRichard Henderson 
7997ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
8007ec8bab3SRichard Henderson     if (ofs + len == 32) {
8017ec8bab3SRichard Henderson         tcg_gen_sari_i32(ret, arg, 32 - len);
8027ec8bab3SRichard Henderson         return;
8037ec8bab3SRichard Henderson     }
8047ec8bab3SRichard Henderson     if (ofs == 0) {
8057ec8bab3SRichard Henderson         switch (len) {
8067ec8bab3SRichard Henderson         case 16:
8077ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
8087ec8bab3SRichard Henderson             return;
8097ec8bab3SRichard Henderson         case 8:
8107ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
8117ec8bab3SRichard Henderson             return;
8127ec8bab3SRichard Henderson         }
8137ec8bab3SRichard Henderson     }
8147ec8bab3SRichard Henderson 
8157ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i32
8167ec8bab3SRichard Henderson         && TCG_TARGET_extract_i32_valid(ofs, len)) {
8177ec8bab3SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len);
8187ec8bab3SRichard Henderson         return;
8197ec8bab3SRichard Henderson     }
8207ec8bab3SRichard Henderson 
8217ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
8227ec8bab3SRichard Henderson     switch (ofs + len) {
8237ec8bab3SRichard Henderson     case 16:
8247ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
8257ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, arg);
8267ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
8277ec8bab3SRichard Henderson             return;
8287ec8bab3SRichard Henderson         }
8297ec8bab3SRichard Henderson         break;
8307ec8bab3SRichard Henderson     case 8:
8317ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8327ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, arg);
8337ec8bab3SRichard Henderson             tcg_gen_sari_i32(ret, ret, ofs);
8347ec8bab3SRichard Henderson             return;
8357ec8bab3SRichard Henderson         }
8367ec8bab3SRichard Henderson         break;
8377ec8bab3SRichard Henderson     }
8387ec8bab3SRichard Henderson     switch (len) {
8397ec8bab3SRichard Henderson     case 16:
8407ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i32) {
8417ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8427ec8bab3SRichard Henderson             tcg_gen_ext16s_i32(ret, ret);
8437ec8bab3SRichard Henderson             return;
8447ec8bab3SRichard Henderson         }
8457ec8bab3SRichard Henderson         break;
8467ec8bab3SRichard Henderson     case 8:
8477ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i32) {
8487ec8bab3SRichard Henderson             tcg_gen_shri_i32(ret, arg, ofs);
8497ec8bab3SRichard Henderson             tcg_gen_ext8s_i32(ret, ret);
8507ec8bab3SRichard Henderson             return;
8517ec8bab3SRichard Henderson         }
8527ec8bab3SRichard Henderson         break;
8537ec8bab3SRichard Henderson     }
8547ec8bab3SRichard Henderson 
8557ec8bab3SRichard Henderson     tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
8567ec8bab3SRichard Henderson     tcg_gen_sari_i32(ret, ret, 32 - len);
8577ec8bab3SRichard Henderson }
8587ec8bab3SRichard Henderson 
859951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
860951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
861951c6300SRichard Henderson {
86237ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
86337ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
86437ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
86537ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
86637ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
867951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
868951c6300SRichard Henderson     } else {
869951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
870951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
871951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
872951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
873951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
874951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
875951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
876951c6300SRichard Henderson         tcg_temp_free_i32(t0);
877951c6300SRichard Henderson         tcg_temp_free_i32(t1);
878951c6300SRichard Henderson     }
879951c6300SRichard Henderson }
880951c6300SRichard Henderson 
881951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
882951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
883951c6300SRichard Henderson {
884951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
885951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
886951c6300SRichard Henderson     } else {
887951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
888951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
889951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
890951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
891951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
892951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
893951c6300SRichard Henderson         tcg_temp_free_i64(t0);
894951c6300SRichard Henderson         tcg_temp_free_i64(t1);
895951c6300SRichard Henderson     }
896951c6300SRichard Henderson }
897951c6300SRichard Henderson 
898951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
899951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
900951c6300SRichard Henderson {
901951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
902951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
903951c6300SRichard Henderson     } else {
904951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
905951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
906951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
907951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
908951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
909951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
910951c6300SRichard Henderson         tcg_temp_free_i64(t0);
911951c6300SRichard Henderson         tcg_temp_free_i64(t1);
912951c6300SRichard Henderson     }
913951c6300SRichard Henderson }
914951c6300SRichard Henderson 
915951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
916951c6300SRichard Henderson {
917951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
918951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
919951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
920951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
921951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
922951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
923951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
924951c6300SRichard Henderson         tcg_temp_free_i32(t);
925951c6300SRichard Henderson     } else {
926951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
927951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
928951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
929951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
930951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
931951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
932951c6300SRichard Henderson         tcg_temp_free_i64(t0);
933951c6300SRichard Henderson         tcg_temp_free_i64(t1);
934951c6300SRichard Henderson     }
935951c6300SRichard Henderson }
936951c6300SRichard Henderson 
937951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
938951c6300SRichard Henderson {
939951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
940951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
941951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
942951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
943951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
944951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
945951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
946951c6300SRichard Henderson         tcg_temp_free_i32(t);
947951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
948951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
949951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
950951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
951951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
952951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
953951c6300SRichard Henderson         /* Adjust for negative inputs.  */
954951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
955951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
956951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
957951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
958951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
959951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
960951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
961951c6300SRichard Henderson         tcg_temp_free_i32(t0);
962951c6300SRichard Henderson         tcg_temp_free_i32(t1);
963951c6300SRichard Henderson         tcg_temp_free_i32(t2);
964951c6300SRichard Henderson         tcg_temp_free_i32(t3);
965951c6300SRichard Henderson     } else {
966951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
967951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
968951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
969951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
970951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
971951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
972951c6300SRichard Henderson         tcg_temp_free_i64(t0);
973951c6300SRichard Henderson         tcg_temp_free_i64(t1);
974951c6300SRichard Henderson     }
975951c6300SRichard Henderson }
976951c6300SRichard Henderson 
9775087abfbSRichard Henderson void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
9785087abfbSRichard Henderson {
9795087abfbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
9805087abfbSRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
9815087abfbSRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
9825087abfbSRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
9835087abfbSRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
9845087abfbSRichard Henderson         /* Adjust for negative input for the signed arg1.  */
9855087abfbSRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
9865087abfbSRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
9875087abfbSRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
9885087abfbSRichard Henderson         tcg_gen_mov_i32(rl, t0);
9895087abfbSRichard Henderson         tcg_temp_free_i32(t0);
9905087abfbSRichard Henderson         tcg_temp_free_i32(t1);
9915087abfbSRichard Henderson         tcg_temp_free_i32(t2);
9925087abfbSRichard Henderson     } else {
9935087abfbSRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
9945087abfbSRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
9955087abfbSRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
9965087abfbSRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
9975087abfbSRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
9985087abfbSRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
9995087abfbSRichard Henderson         tcg_temp_free_i64(t0);
10005087abfbSRichard Henderson         tcg_temp_free_i64(t1);
10015087abfbSRichard Henderson     }
10025087abfbSRichard Henderson }
10035087abfbSRichard Henderson 
1004951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
1005951c6300SRichard Henderson {
1006951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
1007951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
1008951c6300SRichard Henderson     } else {
1009951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
1010951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
1011951c6300SRichard Henderson     }
1012951c6300SRichard Henderson }
1013951c6300SRichard Henderson 
1014951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
1015951c6300SRichard Henderson {
1016951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
1017951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
1018951c6300SRichard Henderson     } else {
1019951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
1020951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
1021951c6300SRichard Henderson     }
1022951c6300SRichard Henderson }
1023951c6300SRichard Henderson 
1024951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
1025951c6300SRichard Henderson {
1026951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
1027951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
1028951c6300SRichard Henderson     } else {
1029951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
1030951c6300SRichard Henderson     }
1031951c6300SRichard Henderson }
1032951c6300SRichard Henderson 
1033951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
1034951c6300SRichard Henderson {
1035951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
1036951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
1037951c6300SRichard Henderson     } else {
1038951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
1039951c6300SRichard Henderson     }
1040951c6300SRichard Henderson }
1041951c6300SRichard Henderson 
1042951c6300SRichard Henderson /* Note: we assume the two high bytes are set to zero */
1043951c6300SRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
1044951c6300SRichard Henderson {
1045951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
1046951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
1047951c6300SRichard Henderson     } else {
1048951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1049951c6300SRichard Henderson 
1050951c6300SRichard Henderson         tcg_gen_ext8u_i32(t0, arg);
1051951c6300SRichard Henderson         tcg_gen_shli_i32(t0, t0, 8);
1052951c6300SRichard Henderson         tcg_gen_shri_i32(ret, arg, 8);
1053951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t0);
1054951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1055951c6300SRichard Henderson     }
1056951c6300SRichard Henderson }
1057951c6300SRichard Henderson 
1058951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
1059951c6300SRichard Henderson {
1060951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
1061951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
1062951c6300SRichard Henderson     } else {
1063951c6300SRichard Henderson         TCGv_i32 t0, t1;
1064951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1065951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1066951c6300SRichard Henderson 
1067951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg, 24);
1068951c6300SRichard Henderson 
1069951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg, 0x0000ff00);
1070951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);
1071951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
1072951c6300SRichard Henderson 
1073951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 8);
1074951c6300SRichard Henderson         tcg_gen_andi_i32(t1, t1, 0x0000ff00);
1075951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
1076951c6300SRichard Henderson 
1077951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 24);
1078951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
1079951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1080951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1081951c6300SRichard Henderson     }
1082951c6300SRichard Henderson }
1083951c6300SRichard Henderson 
1084951c6300SRichard Henderson /* 64-bit ops */
1085951c6300SRichard Henderson 
1086951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
1087951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
1088951c6300SRichard Henderson 
1089951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
1090951c6300SRichard Henderson {
1091951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
1092951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
1093951c6300SRichard Henderson }
1094951c6300SRichard Henderson 
1095951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
1096951c6300SRichard Henderson {
1097951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1098951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1099951c6300SRichard Henderson }
1100951c6300SRichard Henderson 
1101951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
1102951c6300SRichard Henderson {
1103951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
1104951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
1105951c6300SRichard Henderson }
1106951c6300SRichard Henderson 
1107951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1108951c6300SRichard Henderson {
1109951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
1110951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1111951c6300SRichard Henderson }
1112951c6300SRichard Henderson 
1113951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1114951c6300SRichard Henderson {
1115951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
11163ff91d7eSJoseph Myers     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1117951c6300SRichard Henderson }
1118951c6300SRichard Henderson 
1119951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1120951c6300SRichard Henderson {
1121951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
1122951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1123951c6300SRichard Henderson }
1124951c6300SRichard Henderson 
1125951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1126951c6300SRichard Henderson {
1127951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
1128951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1129951c6300SRichard Henderson }
1130951c6300SRichard Henderson 
1131951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1132951c6300SRichard Henderson {
1133951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1134951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1135951c6300SRichard Henderson }
1136951c6300SRichard Henderson 
1137951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1138951c6300SRichard Henderson {
1139951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1140951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1141951c6300SRichard Henderson }
1142951c6300SRichard Henderson 
1143951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
1144951c6300SRichard Henderson {
1145951c6300SRichard Henderson     /* Since arg2 and ret have different types,
1146951c6300SRichard Henderson        they cannot be the same temporary */
1147cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1148951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1149951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1150951c6300SRichard Henderson #else
1151951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1152951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1153951c6300SRichard Henderson #endif
1154951c6300SRichard Henderson }
1155951c6300SRichard Henderson 
1156951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
1157951c6300SRichard Henderson {
1158cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
1159951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1160951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1161951c6300SRichard Henderson #else
1162951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1163951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1164951c6300SRichard Henderson #endif
1165951c6300SRichard Henderson }
1166951c6300SRichard Henderson 
1167951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1168951c6300SRichard Henderson {
1169951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1170951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1171951c6300SRichard Henderson }
1172951c6300SRichard Henderson 
1173951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1174951c6300SRichard Henderson {
1175951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1176951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1177951c6300SRichard Henderson }
1178951c6300SRichard Henderson 
1179951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1180951c6300SRichard Henderson {
1181951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1182951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1183951c6300SRichard Henderson }
1184951c6300SRichard Henderson 
1185951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1186951c6300SRichard Henderson {
1187951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
1188951c6300SRichard Henderson }
1189951c6300SRichard Henderson 
1190951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1191951c6300SRichard Henderson {
1192951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
1193951c6300SRichard Henderson }
1194951c6300SRichard Henderson 
1195951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1196951c6300SRichard Henderson {
1197951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
1198951c6300SRichard Henderson }
1199951c6300SRichard Henderson 
1200951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1201951c6300SRichard Henderson {
1202951c6300SRichard Henderson     TCGv_i64 t0;
1203951c6300SRichard Henderson     TCGv_i32 t1;
1204951c6300SRichard Henderson 
1205951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
1206951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
1207951c6300SRichard Henderson 
1208951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
1209951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
1210951c6300SRichard Henderson 
1211951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
1212951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1213951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
1214951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
1215951c6300SRichard Henderson 
1216951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
1217951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1218951c6300SRichard Henderson     tcg_temp_free_i32(t1);
1219951c6300SRichard Henderson }
1220951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
1221951c6300SRichard Henderson 
1222951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1223951c6300SRichard Henderson {
1224951c6300SRichard Henderson     /* some cases can be optimized here */
1225951c6300SRichard Henderson     if (arg2 == 0) {
1226951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1227951c6300SRichard Henderson     } else {
1228951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1229951c6300SRichard Henderson         tcg_gen_add_i64(ret, arg1, t0);
1230951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1231951c6300SRichard Henderson     }
1232951c6300SRichard Henderson }
1233951c6300SRichard Henderson 
1234951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
1235951c6300SRichard Henderson {
1236951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
1237951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
1238951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
1239951c6300SRichard Henderson     } else {
1240951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg1);
1241951c6300SRichard Henderson         tcg_gen_sub_i64(ret, t0, arg2);
1242951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1243951c6300SRichard Henderson     }
1244951c6300SRichard Henderson }
1245951c6300SRichard Henderson 
1246951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1247951c6300SRichard Henderson {
1248951c6300SRichard Henderson     /* some cases can be optimized here */
1249951c6300SRichard Henderson     if (arg2 == 0) {
1250951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1251951c6300SRichard Henderson     } else {
1252951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1253951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1254951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1255951c6300SRichard Henderson     }
1256951c6300SRichard Henderson }
1257951c6300SRichard Henderson 
1258951c6300SRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
1259951c6300SRichard Henderson {
12603a13c3f3SRichard Henderson     TCGv_i64 t0;
12613a13c3f3SRichard Henderson 
12623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1263951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1264951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
12653a13c3f3SRichard Henderson         return;
12663a13c3f3SRichard Henderson     }
12673a13c3f3SRichard Henderson 
1268951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1269951c6300SRichard Henderson     switch (arg2) {
1270951c6300SRichard Henderson     case 0:
1271951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1272951c6300SRichard Henderson         return;
1273951c6300SRichard Henderson     case 0xffffffffffffffffull:
1274951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1275951c6300SRichard Henderson         return;
1276951c6300SRichard Henderson     case 0xffull:
1277951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
1278951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
1279951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
1280951c6300SRichard Henderson             return;
1281951c6300SRichard Henderson         }
1282951c6300SRichard Henderson         break;
1283951c6300SRichard Henderson     case 0xffffu:
1284951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
1285951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1286951c6300SRichard Henderson             return;
1287951c6300SRichard Henderson         }
1288951c6300SRichard Henderson         break;
1289951c6300SRichard Henderson     case 0xffffffffull:
1290951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
1291951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1292951c6300SRichard Henderson             return;
1293951c6300SRichard Henderson         }
1294951c6300SRichard Henderson         break;
1295951c6300SRichard Henderson     }
1296951c6300SRichard Henderson     t0 = tcg_const_i64(arg2);
1297951c6300SRichard Henderson     tcg_gen_and_i64(ret, arg1, t0);
1298951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1299951c6300SRichard Henderson }
1300951c6300SRichard Henderson 
1301951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1302951c6300SRichard Henderson {
13033a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1304951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1305951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13063a13c3f3SRichard Henderson         return;
13073a13c3f3SRichard Henderson     }
1308951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1309951c6300SRichard Henderson     if (arg2 == -1) {
1310951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
1311951c6300SRichard Henderson     } else if (arg2 == 0) {
1312951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1313951c6300SRichard Henderson     } else {
1314951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1315951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1316951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1317951c6300SRichard Henderson     }
1318951c6300SRichard Henderson }
1319951c6300SRichard Henderson 
1320951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1321951c6300SRichard Henderson {
13223a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1323951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1324951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
13253a13c3f3SRichard Henderson         return;
13263a13c3f3SRichard Henderson     }
1327951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1328951c6300SRichard Henderson     if (arg2 == 0) {
1329951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1330951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1331951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1332951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1333951c6300SRichard Henderson     } else {
1334951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1335951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, t0);
1336951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1337951c6300SRichard Henderson     }
1338951c6300SRichard Henderson }
1339951c6300SRichard Henderson 
1340951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1341951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1342951c6300SRichard Henderson {
1343951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1344951c6300SRichard Henderson     if (c == 0) {
1345951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1346951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1347951c6300SRichard Henderson     } else if (c >= 32) {
1348951c6300SRichard Henderson         c -= 32;
1349951c6300SRichard Henderson         if (right) {
1350951c6300SRichard Henderson             if (arith) {
1351951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1352951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1353951c6300SRichard Henderson             } else {
1354951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1355951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1356951c6300SRichard Henderson             }
1357951c6300SRichard Henderson         } else {
1358951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1359951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1360951c6300SRichard Henderson         }
1361951c6300SRichard Henderson     } else {
1362951c6300SRichard Henderson         TCGv_i32 t0, t1;
1363951c6300SRichard Henderson 
1364951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1365951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1366951c6300SRichard Henderson         if (right) {
1367951c6300SRichard Henderson             tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
1368951c6300SRichard Henderson             if (arith) {
1369951c6300SRichard Henderson                 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
1370951c6300SRichard Henderson             } else {
1371951c6300SRichard Henderson                 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
1372951c6300SRichard Henderson             }
1373951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1374951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
1375951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
1376951c6300SRichard Henderson         } else {
1377951c6300SRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
1378951c6300SRichard Henderson             /* Note: ret can be the same as arg1, so we use t1 */
1379951c6300SRichard Henderson             tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
1380951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1381951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
1382951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1383951c6300SRichard Henderson         }
1384951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1385951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1386951c6300SRichard Henderson     }
1387951c6300SRichard Henderson }
1388951c6300SRichard Henderson 
1389951c6300SRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1390951c6300SRichard Henderson {
1391951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
13923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
13933a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
13943a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1395951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1396951c6300SRichard Henderson     } else {
1397951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1398951c6300SRichard Henderson         tcg_gen_shl_i64(ret, arg1, t0);
1399951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1400951c6300SRichard Henderson     }
1401951c6300SRichard Henderson }
1402951c6300SRichard Henderson 
1403951c6300SRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1404951c6300SRichard Henderson {
1405951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
14063a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14073a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
14083a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1409951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1410951c6300SRichard Henderson     } else {
1411951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1412951c6300SRichard Henderson         tcg_gen_shr_i64(ret, arg1, t0);
1413951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1414951c6300SRichard Henderson     }
1415951c6300SRichard Henderson }
1416951c6300SRichard Henderson 
1417951c6300SRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1418951c6300SRichard Henderson {
1419951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
14203a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14213a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
14223a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1423951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1424951c6300SRichard Henderson     } else {
1425951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1426951c6300SRichard Henderson         tcg_gen_sar_i64(ret, arg1, t0);
1427951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1428951c6300SRichard Henderson     }
1429951c6300SRichard Henderson }
1430951c6300SRichard Henderson 
143142a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1432951c6300SRichard Henderson {
1433951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
143442a268c2SRichard Henderson         tcg_gen_br(l);
1435951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
14363a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1437951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1438951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
143942a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
14403a13c3f3SRichard Henderson         } else {
144142a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
144242a268c2SRichard Henderson                               label_arg(l));
14433a13c3f3SRichard Henderson         }
1444951c6300SRichard Henderson     }
1445951c6300SRichard Henderson }
1446951c6300SRichard Henderson 
144742a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1448951c6300SRichard Henderson {
1449951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
145042a268c2SRichard Henderson         tcg_gen_br(l);
1451951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1452951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
145342a268c2SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, t0, l);
1454951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1455951c6300SRichard Henderson     }
1456951c6300SRichard Henderson }
1457951c6300SRichard Henderson 
1458951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1459951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1460951c6300SRichard Henderson {
1461951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1462951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1463951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1464951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1465951c6300SRichard Henderson     } else {
14663a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1467951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1468951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1469951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1470951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
14713a13c3f3SRichard Henderson         } else {
1472951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
14733a13c3f3SRichard Henderson         }
1474951c6300SRichard Henderson     }
1475951c6300SRichard Henderson }
1476951c6300SRichard Henderson 
1477951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1478951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1479951c6300SRichard Henderson {
1480951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1481951c6300SRichard Henderson     tcg_gen_setcond_i64(cond, ret, arg1, t0);
1482951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1483951c6300SRichard Henderson }
1484951c6300SRichard Henderson 
1485951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1486951c6300SRichard Henderson {
1487951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1488951c6300SRichard Henderson     tcg_gen_mul_i64(ret, arg1, t0);
1489951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1490951c6300SRichard Henderson }
1491951c6300SRichard Henderson 
1492951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1493951c6300SRichard Henderson {
1494951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1495951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1496951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1497951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1498951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1499951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1500951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1501951c6300SRichard Henderson     } else {
1502951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1503951c6300SRichard Henderson     }
1504951c6300SRichard Henderson }
1505951c6300SRichard Henderson 
1506951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1507951c6300SRichard Henderson {
1508951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1509951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1510951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1511951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1512951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1513951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1514951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1515951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1516951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1517951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1518951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1519951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1520951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1521951c6300SRichard Henderson     } else {
1522951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1523951c6300SRichard Henderson     }
1524951c6300SRichard Henderson }
1525951c6300SRichard Henderson 
1526951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1527951c6300SRichard Henderson {
1528951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1529951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1530951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1531951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1532951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1533951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1534951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1535951c6300SRichard Henderson     } else {
1536951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1537951c6300SRichard Henderson     }
1538951c6300SRichard Henderson }
1539951c6300SRichard Henderson 
1540951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1541951c6300SRichard Henderson {
1542951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1543951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1544951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1545951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1546951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1547951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1548951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1549951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1550951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1551951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1552951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1553951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1554951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1555951c6300SRichard Henderson     } else {
1556951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1557951c6300SRichard Henderson     }
1558951c6300SRichard Henderson }
1559951c6300SRichard Henderson 
1560951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1561951c6300SRichard Henderson {
15623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1563951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1564951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15653a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1566951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1567951c6300SRichard Henderson     } else {
1568951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1569951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1570951c6300SRichard Henderson     }
1571951c6300SRichard Henderson }
1572951c6300SRichard Henderson 
1573951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1574951c6300SRichard Henderson {
15753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1576951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1577951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15783a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1579951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1580951c6300SRichard Henderson     } else {
1581951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1582951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1583951c6300SRichard Henderson     }
1584951c6300SRichard Henderson }
1585951c6300SRichard Henderson 
1586951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1587951c6300SRichard Henderson {
15883a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1589951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1590951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
15913a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1592951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1593951c6300SRichard Henderson     } else {
1594951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1595951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1596951c6300SRichard Henderson     }
1597951c6300SRichard Henderson }
1598951c6300SRichard Henderson 
1599951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1600951c6300SRichard Henderson {
16013a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1602951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1603951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16043a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1605951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1606951c6300SRichard Henderson     } else {
1607951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1608951c6300SRichard Henderson     }
1609951c6300SRichard Henderson }
1610951c6300SRichard Henderson 
1611951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1612951c6300SRichard Henderson {
16133a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1614951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1615951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16163a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1617951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1618951c6300SRichard Henderson     } else {
1619951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1620951c6300SRichard Henderson     }
1621951c6300SRichard Henderson }
1622951c6300SRichard Henderson 
1623951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1624951c6300SRichard Henderson {
16253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1626951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1627951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16283a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1629951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1630951c6300SRichard Henderson     } else {
1631951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1632951c6300SRichard Henderson     }
1633951c6300SRichard Henderson }
1634951c6300SRichard Henderson 
1635951c6300SRichard Henderson /* Note: we assume the six high bytes are set to zero */
1636951c6300SRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
1637951c6300SRichard Henderson {
16383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1639951c6300SRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1640951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16413a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
1642951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
1643951c6300SRichard Henderson     } else {
1644951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1645951c6300SRichard Henderson 
1646951c6300SRichard Henderson         tcg_gen_ext8u_i64(t0, arg);
1647951c6300SRichard Henderson         tcg_gen_shli_i64(t0, t0, 8);
1648951c6300SRichard Henderson         tcg_gen_shri_i64(ret, arg, 8);
1649951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t0);
1650951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1651951c6300SRichard Henderson     }
1652951c6300SRichard Henderson }
1653951c6300SRichard Henderson 
1654951c6300SRichard Henderson /* Note: we assume the four high bytes are set to zero */
1655951c6300SRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
1656951c6300SRichard Henderson {
16573a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1658951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1659951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
16603a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
1661951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
1662951c6300SRichard Henderson     } else {
1663951c6300SRichard Henderson         TCGv_i64 t0, t1;
1664951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1665951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1666951c6300SRichard Henderson 
1667951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 24);
1668951c6300SRichard Henderson         tcg_gen_ext32u_i64(t0, t0);
1669951c6300SRichard Henderson 
1670951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1671951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1672951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1673951c6300SRichard Henderson 
1674951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1675951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1676951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1677951c6300SRichard Henderson 
1678951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1679951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1680951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1681951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1682951c6300SRichard Henderson     }
1683951c6300SRichard Henderson }
1684951c6300SRichard Henderson 
1685951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1686951c6300SRichard Henderson {
16873a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1688951c6300SRichard Henderson         TCGv_i32 t0, t1;
1689951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1690951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1691951c6300SRichard Henderson 
1692951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1693951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1694951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1695951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1696951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1697951c6300SRichard Henderson         tcg_temp_free_i32(t1);
16983a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1699951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
1700951c6300SRichard Henderson     } else {
1701951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1702951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1703951c6300SRichard Henderson 
1704951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 56);
1705951c6300SRichard Henderson 
1706951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1707951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 40);
1708951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1709951c6300SRichard Henderson 
1710951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x00ff0000);
1711951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 24);
1712951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1713951c6300SRichard Henderson 
1714951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0xff000000);
1715951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1716951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1717951c6300SRichard Henderson 
1718951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1719951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0xff000000);
1720951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1721951c6300SRichard Henderson 
1722951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1723951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x00ff0000);
1724951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1725951c6300SRichard Henderson 
1726951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 40);
1727951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1728951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1729951c6300SRichard Henderson 
1730951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 56);
1731951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1732951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1733951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1734951c6300SRichard Henderson     }
1735951c6300SRichard Henderson }
1736951c6300SRichard Henderson 
1737951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1738951c6300SRichard Henderson {
17393a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17403a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
17413a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
17423a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1743951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1744951c6300SRichard Henderson     } else {
1745951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1746951c6300SRichard Henderson     }
1747951c6300SRichard Henderson }
1748951c6300SRichard Henderson 
1749951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1750951c6300SRichard Henderson {
17513a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17523a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17533a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1755951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1756951c6300SRichard Henderson     } else {
1757951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1758951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1759951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1760951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1761951c6300SRichard Henderson     }
1762951c6300SRichard Henderson }
1763951c6300SRichard Henderson 
1764951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1765951c6300SRichard Henderson {
17663a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17673a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17683a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17693a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1770951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1771951c6300SRichard Henderson     } else {
1772951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1773951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1774951c6300SRichard Henderson     }
1775951c6300SRichard Henderson }
1776951c6300SRichard Henderson 
1777951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1778951c6300SRichard Henderson {
17793a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17803a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17813a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17823a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1783951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1784951c6300SRichard Henderson     } else {
1785951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1786951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1787951c6300SRichard Henderson     }
1788951c6300SRichard Henderson }
1789951c6300SRichard Henderson 
1790951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1791951c6300SRichard Henderson {
17923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
17933a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
17943a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
17953a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1796951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1797951c6300SRichard Henderson     } else {
1798951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1799951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1800951c6300SRichard Henderson     }
1801951c6300SRichard Henderson }
1802951c6300SRichard Henderson 
1803951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1804951c6300SRichard Henderson {
18053a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
18063a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
18073a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
18083a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1809951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1810951c6300SRichard Henderson     } else {
1811951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1812951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1813951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1814951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1815951c6300SRichard Henderson     }
1816951c6300SRichard Henderson }
1817951c6300SRichard Henderson 
18180e28d006SRichard Henderson void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18190e28d006SRichard Henderson {
18200e28d006SRichard Henderson     if (TCG_TARGET_HAS_clz_i64) {
18210e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_clz_i64, ret, arg1, arg2);
18220e28d006SRichard Henderson     } else {
18230e28d006SRichard Henderson         gen_helper_clz_i64(ret, arg1, arg2);
18240e28d006SRichard Henderson     }
18250e28d006SRichard Henderson }
18260e28d006SRichard Henderson 
18270e28d006SRichard Henderson void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18280e28d006SRichard Henderson {
18290e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18300e28d006SRichard Henderson         && TCG_TARGET_HAS_clz_i32
18310e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18320e28d006SRichard Henderson         TCGv_i32 t = tcg_const_i32((uint32_t)arg2 - 32);
18330e28d006SRichard Henderson         tcg_gen_clz_i32(t, TCGV_LOW(arg1), t);
18340e28d006SRichard Henderson         tcg_gen_addi_i32(t, t, 32);
18350e28d006SRichard Henderson         tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
18360e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18370e28d006SRichard Henderson         tcg_temp_free_i32(t);
18380e28d006SRichard Henderson     } else {
18390e28d006SRichard Henderson         TCGv_i64 t = tcg_const_i64(arg2);
18400e28d006SRichard Henderson         tcg_gen_clz_i64(ret, arg1, t);
18410e28d006SRichard Henderson         tcg_temp_free_i64(t);
18420e28d006SRichard Henderson     }
18430e28d006SRichard Henderson }
18440e28d006SRichard Henderson 
18450e28d006SRichard Henderson void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
18460e28d006SRichard Henderson {
18470e28d006SRichard Henderson     if (TCG_TARGET_HAS_ctz_i64) {
18480e28d006SRichard Henderson         tcg_gen_op3_i64(INDEX_op_ctz_i64, ret, arg1, arg2);
184914e99210SRichard Henderson     } else if (TCG_TARGET_HAS_ctpop_i64 || TCG_TARGET_HAS_clz_i64) {
185014e99210SRichard Henderson         TCGv_i64 z, t = tcg_temp_new_i64();
185114e99210SRichard Henderson 
185214e99210SRichard Henderson         if (TCG_TARGET_HAS_ctpop_i64) {
185314e99210SRichard Henderson             tcg_gen_subi_i64(t, arg1, 1);
185414e99210SRichard Henderson             tcg_gen_andc_i64(t, t, arg1);
185514e99210SRichard Henderson             tcg_gen_ctpop_i64(t, t);
185614e99210SRichard Henderson         } else {
185714e99210SRichard Henderson             /* Since all non-x86 hosts have clz(0) == 64, don't fight it.  */
185814e99210SRichard Henderson             tcg_gen_neg_i64(t, arg1);
185914e99210SRichard Henderson             tcg_gen_and_i64(t, t, arg1);
186014e99210SRichard Henderson             tcg_gen_clzi_i64(t, t, 64);
186114e99210SRichard Henderson             tcg_gen_xori_i64(t, t, 63);
186214e99210SRichard Henderson         }
186314e99210SRichard Henderson         z = tcg_const_i64(0);
186414e99210SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
186514e99210SRichard Henderson         tcg_temp_free_i64(t);
186614e99210SRichard Henderson         tcg_temp_free_i64(z);
18670e28d006SRichard Henderson     } else {
18680e28d006SRichard Henderson         gen_helper_ctz_i64(ret, arg1, arg2);
18690e28d006SRichard Henderson     }
18700e28d006SRichard Henderson }
18710e28d006SRichard Henderson 
18720e28d006SRichard Henderson void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
18730e28d006SRichard Henderson {
18740e28d006SRichard Henderson     if (TCG_TARGET_REG_BITS == 32
18750e28d006SRichard Henderson         && TCG_TARGET_HAS_ctz_i32
18760e28d006SRichard Henderson         && arg2 <= 0xffffffffu) {
18770e28d006SRichard Henderson         TCGv_i32 t32 = tcg_const_i32((uint32_t)arg2 - 32);
18780e28d006SRichard Henderson         tcg_gen_ctz_i32(t32, TCGV_HIGH(arg1), t32);
18790e28d006SRichard Henderson         tcg_gen_addi_i32(t32, t32, 32);
18800e28d006SRichard Henderson         tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
18810e28d006SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
18820e28d006SRichard Henderson         tcg_temp_free_i32(t32);
188314e99210SRichard Henderson     } else if (!TCG_TARGET_HAS_ctz_i64
188414e99210SRichard Henderson                && TCG_TARGET_HAS_ctpop_i64
188514e99210SRichard Henderson                && arg2 == 64) {
188614e99210SRichard Henderson         /* This equivalence has the advantage of not requiring a fixup.  */
188714e99210SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
188814e99210SRichard Henderson         tcg_gen_subi_i64(t, arg1, 1);
188914e99210SRichard Henderson         tcg_gen_andc_i64(t, t, arg1);
189014e99210SRichard Henderson         tcg_gen_ctpop_i64(ret, t);
189114e99210SRichard Henderson         tcg_temp_free_i64(t);
18920e28d006SRichard Henderson     } else {
18930e28d006SRichard Henderson         TCGv_i64 t64 = tcg_const_i64(arg2);
18940e28d006SRichard Henderson         tcg_gen_ctz_i64(ret, arg1, t64);
18950e28d006SRichard Henderson         tcg_temp_free_i64(t64);
18960e28d006SRichard Henderson     }
18970e28d006SRichard Henderson }
18980e28d006SRichard Henderson 
1899086920c2SRichard Henderson void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg)
1900086920c2SRichard Henderson {
1901086920c2SRichard Henderson     if (TCG_TARGET_HAS_clz_i64 || TCG_TARGET_HAS_clz_i32) {
1902086920c2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1903086920c2SRichard Henderson         tcg_gen_sari_i64(t, arg, 63);
1904086920c2SRichard Henderson         tcg_gen_xor_i64(t, t, arg);
1905086920c2SRichard Henderson         tcg_gen_clzi_i64(t, t, 64);
1906086920c2SRichard Henderson         tcg_gen_subi_i64(ret, t, 1);
1907086920c2SRichard Henderson         tcg_temp_free_i64(t);
1908086920c2SRichard Henderson     } else {
1909086920c2SRichard Henderson         gen_helper_clrsb_i64(ret, arg);
1910086920c2SRichard Henderson     }
1911086920c2SRichard Henderson }
1912086920c2SRichard Henderson 
1913a768e4e9SRichard Henderson void tcg_gen_ctpop_i64(TCGv_i64 ret, TCGv_i64 arg1)
1914a768e4e9SRichard Henderson {
1915a768e4e9SRichard Henderson     if (TCG_TARGET_HAS_ctpop_i64) {
1916a768e4e9SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ctpop_i64, ret, arg1);
1917a768e4e9SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_ctpop_i32) {
1918a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1919a768e4e9SRichard Henderson         tcg_gen_ctpop_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1920a768e4e9SRichard Henderson         tcg_gen_add_i32(TCGV_LOW(ret), TCGV_LOW(ret), TCGV_HIGH(ret));
1921a768e4e9SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1922a768e4e9SRichard Henderson     } else {
1923a768e4e9SRichard Henderson         gen_helper_ctpop_i64(ret, arg1);
1924a768e4e9SRichard Henderson     }
1925a768e4e9SRichard Henderson }
1926a768e4e9SRichard Henderson 
1927951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1928951c6300SRichard Henderson {
1929951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1930951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1931951c6300SRichard Henderson     } else {
1932951c6300SRichard Henderson         TCGv_i64 t0, t1;
1933951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1934951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1935951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1936951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1937951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1938951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1939951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1940951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1941951c6300SRichard Henderson     }
1942951c6300SRichard Henderson }
1943951c6300SRichard Henderson 
1944951c6300SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1945951c6300SRichard Henderson {
1946951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1947951c6300SRichard Henderson     /* some cases can be optimized here */
1948951c6300SRichard Henderson     if (arg2 == 0) {
1949951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1950951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
1951951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1952951c6300SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, t0);
1953951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1954951c6300SRichard Henderson     } else {
1955951c6300SRichard Henderson         TCGv_i64 t0, t1;
1956951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1957951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1958951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
1959951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
1960951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1961951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1962951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1963951c6300SRichard Henderson     }
1964951c6300SRichard Henderson }
1965951c6300SRichard Henderson 
1966951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1967951c6300SRichard Henderson {
1968951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1969951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
1970951c6300SRichard Henderson     } else {
1971951c6300SRichard Henderson         TCGv_i64 t0, t1;
1972951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1973951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1974951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
1975951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1976951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
1977951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1978951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1979951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1980951c6300SRichard Henderson     }
1981951c6300SRichard Henderson }
1982951c6300SRichard Henderson 
1983951c6300SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1984951c6300SRichard Henderson {
1985951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1986951c6300SRichard Henderson     /* some cases can be optimized here */
1987951c6300SRichard Henderson     if (arg2 == 0) {
1988951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1989951c6300SRichard Henderson     } else {
1990951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
1991951c6300SRichard Henderson     }
1992951c6300SRichard Henderson }
1993951c6300SRichard Henderson 
1994951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
1995951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
1996951c6300SRichard Henderson {
1997951c6300SRichard Henderson     uint64_t mask;
1998951c6300SRichard Henderson     TCGv_i64 t1;
1999951c6300SRichard Henderson 
2000951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
20010d0d309dSRichard Henderson     tcg_debug_assert(len > 0);
2002951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
2003951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
2004951c6300SRichard Henderson 
20050d0d309dSRichard Henderson     if (len == 64) {
2006951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
2007951c6300SRichard Henderson         return;
2008951c6300SRichard Henderson     }
2009951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
2010951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
2011951c6300SRichard Henderson         return;
2012951c6300SRichard Henderson     }
2013951c6300SRichard Henderson 
20143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2015951c6300SRichard Henderson         if (ofs >= 32) {
2016951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
2017951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
2018951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
2019951c6300SRichard Henderson             return;
2020951c6300SRichard Henderson         }
2021951c6300SRichard Henderson         if (ofs + len <= 32) {
2022951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
2023951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
2024951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
2025951c6300SRichard Henderson             return;
2026951c6300SRichard Henderson         }
20273a13c3f3SRichard Henderson     }
2028951c6300SRichard Henderson 
2029951c6300SRichard Henderson     mask = (1ull << len) - 1;
2030951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
2031951c6300SRichard Henderson 
2032951c6300SRichard Henderson     if (ofs + len < 64) {
2033951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
2034951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
2035951c6300SRichard Henderson     } else {
2036951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
2037951c6300SRichard Henderson     }
2038951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
2039951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
2040951c6300SRichard Henderson 
2041951c6300SRichard Henderson     tcg_temp_free_i64(t1);
2042951c6300SRichard Henderson }
2043951c6300SRichard Henderson 
204407cc68d5SRichard Henderson void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
204507cc68d5SRichard Henderson                            unsigned int ofs, unsigned int len)
204607cc68d5SRichard Henderson {
204707cc68d5SRichard Henderson     tcg_debug_assert(ofs < 64);
204807cc68d5SRichard Henderson     tcg_debug_assert(len > 0);
204907cc68d5SRichard Henderson     tcg_debug_assert(len <= 64);
205007cc68d5SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
205107cc68d5SRichard Henderson 
205207cc68d5SRichard Henderson     if (ofs + len == 64) {
205307cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, arg, ofs);
205407cc68d5SRichard Henderson     } else if (ofs == 0) {
205507cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
205607cc68d5SRichard Henderson     } else if (TCG_TARGET_HAS_deposit_i64
205707cc68d5SRichard Henderson                && TCG_TARGET_deposit_i64_valid(ofs, len)) {
205807cc68d5SRichard Henderson         TCGv_i64 zero = tcg_const_i64(0);
205907cc68d5SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
206007cc68d5SRichard Henderson         tcg_temp_free_i64(zero);
206107cc68d5SRichard Henderson     } else {
206207cc68d5SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
206307cc68d5SRichard Henderson             if (ofs >= 32) {
206407cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
206507cc68d5SRichard Henderson                                       ofs - 32, len);
206607cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
206707cc68d5SRichard Henderson                 return;
206807cc68d5SRichard Henderson             }
206907cc68d5SRichard Henderson             if (ofs + len <= 32) {
207007cc68d5SRichard Henderson                 tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
207107cc68d5SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
207207cc68d5SRichard Henderson                 return;
207307cc68d5SRichard Henderson             }
207407cc68d5SRichard Henderson         }
207507cc68d5SRichard Henderson         /* To help two-operand hosts we prefer to zero-extend first,
207607cc68d5SRichard Henderson            which allows ARG to stay live.  */
207707cc68d5SRichard Henderson         switch (len) {
207807cc68d5SRichard Henderson         case 32:
207907cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
208007cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, arg);
208107cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
208207cc68d5SRichard Henderson                 return;
208307cc68d5SRichard Henderson             }
208407cc68d5SRichard Henderson             break;
208507cc68d5SRichard Henderson         case 16:
208607cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
208707cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, arg);
208807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
208907cc68d5SRichard Henderson                 return;
209007cc68d5SRichard Henderson             }
209107cc68d5SRichard Henderson             break;
209207cc68d5SRichard Henderson         case 8:
209307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
209407cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, arg);
209507cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, ret, ofs);
209607cc68d5SRichard Henderson                 return;
209707cc68d5SRichard Henderson             }
209807cc68d5SRichard Henderson             break;
209907cc68d5SRichard Henderson         }
210007cc68d5SRichard Henderson         /* Otherwise prefer zero-extension over AND for code size.  */
210107cc68d5SRichard Henderson         switch (ofs + len) {
210207cc68d5SRichard Henderson         case 32:
210307cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext32u_i64) {
210407cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
210507cc68d5SRichard Henderson                 tcg_gen_ext32u_i64(ret, ret);
210607cc68d5SRichard Henderson                 return;
210707cc68d5SRichard Henderson             }
210807cc68d5SRichard Henderson             break;
210907cc68d5SRichard Henderson         case 16:
211007cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext16u_i64) {
211107cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
211207cc68d5SRichard Henderson                 tcg_gen_ext16u_i64(ret, ret);
211307cc68d5SRichard Henderson                 return;
211407cc68d5SRichard Henderson             }
211507cc68d5SRichard Henderson             break;
211607cc68d5SRichard Henderson         case 8:
211707cc68d5SRichard Henderson             if (TCG_TARGET_HAS_ext8u_i64) {
211807cc68d5SRichard Henderson                 tcg_gen_shli_i64(ret, arg, ofs);
211907cc68d5SRichard Henderson                 tcg_gen_ext8u_i64(ret, ret);
212007cc68d5SRichard Henderson                 return;
212107cc68d5SRichard Henderson             }
212207cc68d5SRichard Henderson             break;
212307cc68d5SRichard Henderson         }
212407cc68d5SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
212507cc68d5SRichard Henderson         tcg_gen_shli_i64(ret, ret, ofs);
212607cc68d5SRichard Henderson     }
212707cc68d5SRichard Henderson }
212807cc68d5SRichard Henderson 
21297ec8bab3SRichard Henderson void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
21307ec8bab3SRichard Henderson                          unsigned int ofs, unsigned int len)
21317ec8bab3SRichard Henderson {
21327ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
21337ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
21347ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
21357ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
21367ec8bab3SRichard Henderson 
21377ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if extract is supported.  */
21387ec8bab3SRichard Henderson     if (ofs + len == 64) {
21397ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, 64 - len);
21407ec8bab3SRichard Henderson         return;
21417ec8bab3SRichard Henderson     }
21427ec8bab3SRichard Henderson     if (ofs == 0) {
21437ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
21447ec8bab3SRichard Henderson         return;
21457ec8bab3SRichard Henderson     }
21467ec8bab3SRichard Henderson 
21477ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
21487ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
21497ec8bab3SRichard Henderson         if (ofs >= 32) {
21507ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
21517ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21527ec8bab3SRichard Henderson             return;
21537ec8bab3SRichard Henderson         }
21547ec8bab3SRichard Henderson         if (ofs + len <= 32) {
21557ec8bab3SRichard Henderson             tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
21567ec8bab3SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
21577ec8bab3SRichard Henderson             return;
21587ec8bab3SRichard Henderson         }
21597ec8bab3SRichard Henderson         /* The field is split across two words.  One double-word
21607ec8bab3SRichard Henderson            shift is better than two double-word shifts.  */
21617ec8bab3SRichard Henderson         goto do_shift_and;
21627ec8bab3SRichard Henderson     }
21637ec8bab3SRichard Henderson 
21647ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_extract_i64
21657ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
21667ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len);
21677ec8bab3SRichard Henderson         return;
21687ec8bab3SRichard Henderson     }
21697ec8bab3SRichard Henderson 
21707ec8bab3SRichard Henderson     /* Assume that zero-extension, if available, is cheaper than a shift.  */
21717ec8bab3SRichard Henderson     switch (ofs + len) {
21727ec8bab3SRichard Henderson     case 32:
21737ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
21747ec8bab3SRichard Henderson             tcg_gen_ext32u_i64(ret, arg);
21757ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21767ec8bab3SRichard Henderson             return;
21777ec8bab3SRichard Henderson         }
21787ec8bab3SRichard Henderson         break;
21797ec8bab3SRichard Henderson     case 16:
21807ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
21817ec8bab3SRichard Henderson             tcg_gen_ext16u_i64(ret, arg);
21827ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21837ec8bab3SRichard Henderson             return;
21847ec8bab3SRichard Henderson         }
21857ec8bab3SRichard Henderson         break;
21867ec8bab3SRichard Henderson     case 8:
21877ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
21887ec8bab3SRichard Henderson             tcg_gen_ext8u_i64(ret, arg);
21897ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, ret, ofs);
21907ec8bab3SRichard Henderson             return;
21917ec8bab3SRichard Henderson         }
21927ec8bab3SRichard Henderson         break;
21937ec8bab3SRichard Henderson     }
21947ec8bab3SRichard Henderson 
21957ec8bab3SRichard Henderson     /* ??? Ideally we'd know what values are available for immediate AND.
21967ec8bab3SRichard Henderson        Assume that 8 bits are available, plus the special cases of 16 and 32,
21977ec8bab3SRichard Henderson        so that we get ext8u, ext16u, and ext32u.  */
21987ec8bab3SRichard Henderson     switch (len) {
21997ec8bab3SRichard Henderson     case 1 ... 8: case 16: case 32:
22007ec8bab3SRichard Henderson     do_shift_and:
22017ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, arg, ofs);
22027ec8bab3SRichard Henderson         tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
22037ec8bab3SRichard Henderson         break;
22047ec8bab3SRichard Henderson     default:
22057ec8bab3SRichard Henderson         tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
22067ec8bab3SRichard Henderson         tcg_gen_shri_i64(ret, ret, 64 - len);
22077ec8bab3SRichard Henderson         break;
22087ec8bab3SRichard Henderson     }
22097ec8bab3SRichard Henderson }
22107ec8bab3SRichard Henderson 
22117ec8bab3SRichard Henderson void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
22127ec8bab3SRichard Henderson                           unsigned int ofs, unsigned int len)
22137ec8bab3SRichard Henderson {
22147ec8bab3SRichard Henderson     tcg_debug_assert(ofs < 64);
22157ec8bab3SRichard Henderson     tcg_debug_assert(len > 0);
22167ec8bab3SRichard Henderson     tcg_debug_assert(len <= 64);
22177ec8bab3SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
22187ec8bab3SRichard Henderson 
22197ec8bab3SRichard Henderson     /* Canonicalize certain special cases, even if sextract is supported.  */
22207ec8bab3SRichard Henderson     if (ofs + len == 64) {
22217ec8bab3SRichard Henderson         tcg_gen_sari_i64(ret, arg, 64 - len);
22227ec8bab3SRichard Henderson         return;
22237ec8bab3SRichard Henderson     }
22247ec8bab3SRichard Henderson     if (ofs == 0) {
22257ec8bab3SRichard Henderson         switch (len) {
22267ec8bab3SRichard Henderson         case 32:
22277ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22287ec8bab3SRichard Henderson             return;
22297ec8bab3SRichard Henderson         case 16:
22307ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22317ec8bab3SRichard Henderson             return;
22327ec8bab3SRichard Henderson         case 8:
22337ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22347ec8bab3SRichard Henderson             return;
22357ec8bab3SRichard Henderson         }
22367ec8bab3SRichard Henderson     }
22377ec8bab3SRichard Henderson 
22387ec8bab3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
22397ec8bab3SRichard Henderson         /* Look for a 32-bit extract within one of the two words.  */
22407ec8bab3SRichard Henderson         if (ofs >= 32) {
22417ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
22427ec8bab3SRichard Henderson         } else if (ofs + len <= 32) {
22437ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len);
22447ec8bab3SRichard Henderson         } else if (ofs == 0) {
22457ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
22467ec8bab3SRichard Henderson             tcg_gen_sextract_i32(TCGV_HIGH(ret), TCGV_HIGH(arg), 0, len - 32);
22477ec8bab3SRichard Henderson             return;
22487ec8bab3SRichard Henderson         } else if (len > 32) {
22497ec8bab3SRichard Henderson             TCGv_i32 t = tcg_temp_new_i32();
22507ec8bab3SRichard Henderson             /* Extract the bits for the high word normally.  */
22517ec8bab3SRichard Henderson             tcg_gen_sextract_i32(t, TCGV_HIGH(arg), ofs + 32, len - 32);
22527ec8bab3SRichard Henderson             /* Shift the field down for the low part.  */
22537ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
22547ec8bab3SRichard Henderson             /* Overwrite the shift into the high part.  */
22557ec8bab3SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t);
22567ec8bab3SRichard Henderson             tcg_temp_free_i32(t);
22577ec8bab3SRichard Henderson             return;
22587ec8bab3SRichard Henderson         } else {
22597ec8bab3SRichard Henderson             /* Shift the field down for the low part, such that the
22607ec8bab3SRichard Henderson                field sits at the MSB.  */
22617ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs + len - 32);
22627ec8bab3SRichard Henderson             /* Shift the field down from the MSB, sign extending.  */
22637ec8bab3SRichard Henderson             tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_LOW(ret), 32 - len);
22647ec8bab3SRichard Henderson         }
22657ec8bab3SRichard Henderson         /* Sign-extend the field from 32 bits.  */
22667ec8bab3SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
22677ec8bab3SRichard Henderson         return;
22687ec8bab3SRichard Henderson     }
22697ec8bab3SRichard Henderson 
22707ec8bab3SRichard Henderson     if (TCG_TARGET_HAS_sextract_i64
22717ec8bab3SRichard Henderson         && TCG_TARGET_extract_i64_valid(ofs, len)) {
22727ec8bab3SRichard Henderson         tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len);
22737ec8bab3SRichard Henderson         return;
22747ec8bab3SRichard Henderson     }
22757ec8bab3SRichard Henderson 
22767ec8bab3SRichard Henderson     /* Assume that sign-extension, if available, is cheaper than a shift.  */
22777ec8bab3SRichard Henderson     switch (ofs + len) {
22787ec8bab3SRichard Henderson     case 32:
22797ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
22807ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, arg);
22817ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22827ec8bab3SRichard Henderson             return;
22837ec8bab3SRichard Henderson         }
22847ec8bab3SRichard Henderson         break;
22857ec8bab3SRichard Henderson     case 16:
22867ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
22877ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, arg);
22887ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22897ec8bab3SRichard Henderson             return;
22907ec8bab3SRichard Henderson         }
22917ec8bab3SRichard Henderson         break;
22927ec8bab3SRichard Henderson     case 8:
22937ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
22947ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, arg);
22957ec8bab3SRichard Henderson             tcg_gen_sari_i64(ret, ret, ofs);
22967ec8bab3SRichard Henderson             return;
22977ec8bab3SRichard Henderson         }
22987ec8bab3SRichard Henderson         break;
22997ec8bab3SRichard Henderson     }
23007ec8bab3SRichard Henderson     switch (len) {
23017ec8bab3SRichard Henderson     case 32:
23027ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext32s_i64) {
23037ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23047ec8bab3SRichard Henderson             tcg_gen_ext32s_i64(ret, ret);
23057ec8bab3SRichard Henderson             return;
23067ec8bab3SRichard Henderson         }
23077ec8bab3SRichard Henderson         break;
23087ec8bab3SRichard Henderson     case 16:
23097ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext16s_i64) {
23107ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23117ec8bab3SRichard Henderson             tcg_gen_ext16s_i64(ret, ret);
23127ec8bab3SRichard Henderson             return;
23137ec8bab3SRichard Henderson         }
23147ec8bab3SRichard Henderson         break;
23157ec8bab3SRichard Henderson     case 8:
23167ec8bab3SRichard Henderson         if (TCG_TARGET_HAS_ext8s_i64) {
23177ec8bab3SRichard Henderson             tcg_gen_shri_i64(ret, arg, ofs);
23187ec8bab3SRichard Henderson             tcg_gen_ext8s_i64(ret, ret);
23197ec8bab3SRichard Henderson             return;
23207ec8bab3SRichard Henderson         }
23217ec8bab3SRichard Henderson         break;
23227ec8bab3SRichard Henderson     }
23237ec8bab3SRichard Henderson     tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
23247ec8bab3SRichard Henderson     tcg_gen_sari_i64(ret, ret, 64 - len);
23257ec8bab3SRichard Henderson }
23267ec8bab3SRichard Henderson 
2327951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
2328951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
2329951c6300SRichard Henderson {
233037ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
233137ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
233237ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
233337ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
233437ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
2335951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
2336951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2337951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
2338951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
2339951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
2340951c6300SRichard Henderson 
2341951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
2342951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
2343951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
2344951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
2345951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
2346951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
2347951c6300SRichard Henderson         } else {
2348951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
2349951c6300SRichard Henderson 
2350951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
2351951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
2352951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
2353951c6300SRichard Henderson 
2354951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
2355951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
2356951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
2357951c6300SRichard Henderson         }
2358951c6300SRichard Henderson         tcg_temp_free_i32(t0);
2359951c6300SRichard Henderson         tcg_temp_free_i32(t1);
23603a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
2361951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
2362951c6300SRichard Henderson     } else {
2363951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2364951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2365951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
2366951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
2367951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
2368951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
2369951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
2370951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2371951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2372951c6300SRichard Henderson     }
2373951c6300SRichard Henderson }
2374951c6300SRichard Henderson 
2375951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2376951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2377951c6300SRichard Henderson {
2378951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
2379951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
2380951c6300SRichard Henderson     } else {
2381951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2382951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2383951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
2384951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
2385951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
2386951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
2387951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2388951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2389951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2390951c6300SRichard Henderson     }
2391951c6300SRichard Henderson }
2392951c6300SRichard Henderson 
2393951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2394951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2395951c6300SRichard Henderson {
2396951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
2397951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
2398951c6300SRichard Henderson     } else {
2399951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2400951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2401951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
2402951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
2403951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
2404951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
2405951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2406951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2407951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2408951c6300SRichard Henderson     }
2409951c6300SRichard Henderson }
2410951c6300SRichard Henderson 
2411951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2412951c6300SRichard Henderson {
2413951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
2414951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
2415951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
2416951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2417951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2418951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
2419951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2420951c6300SRichard Henderson         tcg_temp_free_i64(t);
2421951c6300SRichard Henderson     } else {
2422951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2423951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2424951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
2425951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2426951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2427951c6300SRichard Henderson     }
2428951c6300SRichard Henderson }
2429951c6300SRichard Henderson 
2430951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
2431951c6300SRichard Henderson {
2432951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
2433951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
2434951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
2435951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2436951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
2437951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
2438951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
2439951c6300SRichard Henderson         tcg_temp_free_i64(t);
2440951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
2441951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2442951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2443951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2444951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
2445951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
2446951c6300SRichard Henderson         /* Adjust for negative inputs.  */
2447951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
2448951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
2449951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
2450951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
2451951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
2452951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
2453951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2454951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2455951c6300SRichard Henderson         tcg_temp_free_i64(t1);
2456951c6300SRichard Henderson         tcg_temp_free_i64(t2);
2457951c6300SRichard Henderson         tcg_temp_free_i64(t3);
2458951c6300SRichard Henderson     } else {
2459951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
2460951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
2461951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
2462951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
2463951c6300SRichard Henderson         tcg_temp_free_i64(t0);
2464951c6300SRichard Henderson     }
2465951c6300SRichard Henderson }
2466951c6300SRichard Henderson 
24675087abfbSRichard Henderson void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
24685087abfbSRichard Henderson {
24695087abfbSRichard Henderson     TCGv_i64 t0 = tcg_temp_new_i64();
24705087abfbSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
24715087abfbSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
24725087abfbSRichard Henderson     tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
24735087abfbSRichard Henderson     /* Adjust for negative input for the signed arg1.  */
24745087abfbSRichard Henderson     tcg_gen_sari_i64(t2, arg1, 63);
24755087abfbSRichard Henderson     tcg_gen_and_i64(t2, t2, arg2);
24765087abfbSRichard Henderson     tcg_gen_sub_i64(rh, t1, t2);
24775087abfbSRichard Henderson     tcg_gen_mov_i64(rl, t0);
24785087abfbSRichard Henderson     tcg_temp_free_i64(t0);
24795087abfbSRichard Henderson     tcg_temp_free_i64(t1);
24805087abfbSRichard Henderson     tcg_temp_free_i64(t2);
24815087abfbSRichard Henderson }
24825087abfbSRichard Henderson 
2483951c6300SRichard Henderson /* Size changing operations.  */
2484951c6300SRichard Henderson 
2485609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2486951c6300SRichard Henderson {
24873a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2488951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
2489609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
2490609ad705SRichard Henderson         tcg_gen_op2(&tcg_ctx, INDEX_op_extrl_i64_i32,
2491609ad705SRichard Henderson                     GET_TCGV_I32(ret), GET_TCGV_I64(arg));
2492951c6300SRichard Henderson     } else {
2493951c6300SRichard Henderson         tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
2494609ad705SRichard Henderson     }
2495609ad705SRichard Henderson }
2496609ad705SRichard Henderson 
2497609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
2498609ad705SRichard Henderson {
2499609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2500609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
2501609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
2502609ad705SRichard Henderson         tcg_gen_op2(&tcg_ctx, INDEX_op_extrh_i64_i32,
2503609ad705SRichard Henderson                     GET_TCGV_I32(ret), GET_TCGV_I64(arg));
2504951c6300SRichard Henderson     } else {
2505951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
2506609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
2507951c6300SRichard Henderson         tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(t)));
2508951c6300SRichard Henderson         tcg_temp_free_i64(t);
2509951c6300SRichard Henderson     }
2510951c6300SRichard Henderson }
2511951c6300SRichard Henderson 
2512951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2513951c6300SRichard Henderson {
25143a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2515951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2516951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
25173a13c3f3SRichard Henderson     } else {
25184f2331e5SAurelien Jarno         tcg_gen_op2(&tcg_ctx, INDEX_op_extu_i32_i64,
25194f2331e5SAurelien Jarno                     GET_TCGV_I64(ret), GET_TCGV_I32(arg));
25203a13c3f3SRichard Henderson     }
2521951c6300SRichard Henderson }
2522951c6300SRichard Henderson 
2523951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
2524951c6300SRichard Henderson {
25253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2526951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
2527951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
25283a13c3f3SRichard Henderson     } else {
25294f2331e5SAurelien Jarno         tcg_gen_op2(&tcg_ctx, INDEX_op_ext_i32_i64,
25304f2331e5SAurelien Jarno                     GET_TCGV_I64(ret), GET_TCGV_I32(arg));
25313a13c3f3SRichard Henderson     }
2532951c6300SRichard Henderson }
2533951c6300SRichard Henderson 
2534951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
2535951c6300SRichard Henderson {
25363a13c3f3SRichard Henderson     TCGv_i64 tmp;
25373a13c3f3SRichard Henderson 
25383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2539951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
2540951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
25413a13c3f3SRichard Henderson         return;
25423a13c3f3SRichard Henderson     }
25433a13c3f3SRichard Henderson 
25443a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
2545951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
2546951c6300SRichard Henderson        We may be able to do better given target specific information.  */
2547951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
2548951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
2549951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
2550951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
2551951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
2552951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
2553951c6300SRichard Henderson     } else {
2554951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
2555951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
2556951c6300SRichard Henderson     }
2557951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
2558951c6300SRichard Henderson }
2559951c6300SRichard Henderson 
2560951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
2561951c6300SRichard Henderson {
25623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
2563951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
2564951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
25653a13c3f3SRichard Henderson     } else {
2566609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
2567609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
25683a13c3f3SRichard Henderson     }
2569951c6300SRichard Henderson }
2570951c6300SRichard Henderson 
2571951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
2572951c6300SRichard Henderson {
2573951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
2574951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
2575951c6300SRichard Henderson }
2576951c6300SRichard Henderson 
2577951c6300SRichard Henderson /* QEMU specific operations.  */
2578951c6300SRichard Henderson 
2579951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
2580951c6300SRichard Henderson {
2581951c6300SRichard Henderson     /* We only support two chained exits.  */
2582951c6300SRichard Henderson     tcg_debug_assert(idx <= 1);
2583951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
2584951c6300SRichard Henderson     /* Verify that we havn't seen this numbered exit before.  */
2585951c6300SRichard Henderson     tcg_debug_assert((tcg_ctx.goto_tb_issue_mask & (1 << idx)) == 0);
2586951c6300SRichard Henderson     tcg_ctx.goto_tb_issue_mask |= 1 << idx;
2587951c6300SRichard Henderson #endif
2588951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
2589951c6300SRichard Henderson }
2590951c6300SRichard Henderson 
2591cedbcb01SEmilio G. Cota void tcg_gen_lookup_and_goto_ptr(TCGv addr)
2592cedbcb01SEmilio G. Cota {
2593cedbcb01SEmilio G. Cota     if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
2594cedbcb01SEmilio G. Cota         TCGv_ptr ptr = tcg_temp_new_ptr();
2595cedbcb01SEmilio G. Cota         gen_helper_lookup_tb_ptr(ptr, tcg_ctx.tcg_env, addr);
2596cedbcb01SEmilio G. Cota         tcg_gen_op1i(INDEX_op_goto_ptr, GET_TCGV_PTR(ptr));
2597cedbcb01SEmilio G. Cota         tcg_temp_free_ptr(ptr);
2598cedbcb01SEmilio G. Cota     } else {
2599cedbcb01SEmilio G. Cota         tcg_gen_exit_tb(0);
2600cedbcb01SEmilio G. Cota     }
2601cedbcb01SEmilio G. Cota }
2602cedbcb01SEmilio G. Cota 
2603951c6300SRichard Henderson static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
2604951c6300SRichard Henderson {
26051f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
26061f00b27fSSergey Sorokin     (void)get_alignment_bits(op);
26071f00b27fSSergey Sorokin 
2608951c6300SRichard Henderson     switch (op & MO_SIZE) {
2609951c6300SRichard Henderson     case MO_8:
2610951c6300SRichard Henderson         op &= ~MO_BSWAP;
2611951c6300SRichard Henderson         break;
2612951c6300SRichard Henderson     case MO_16:
2613951c6300SRichard Henderson         break;
2614951c6300SRichard Henderson     case MO_32:
2615951c6300SRichard Henderson         if (!is64) {
2616951c6300SRichard Henderson             op &= ~MO_SIGN;
2617951c6300SRichard Henderson         }
2618951c6300SRichard Henderson         break;
2619951c6300SRichard Henderson     case MO_64:
2620951c6300SRichard Henderson         if (!is64) {
2621951c6300SRichard Henderson             tcg_abort();
2622951c6300SRichard Henderson         }
2623951c6300SRichard Henderson         break;
2624951c6300SRichard Henderson     }
2625951c6300SRichard Henderson     if (st) {
2626951c6300SRichard Henderson         op &= ~MO_SIGN;
2627951c6300SRichard Henderson     }
2628951c6300SRichard Henderson     return op;
2629951c6300SRichard Henderson }
2630951c6300SRichard Henderson 
2631c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
2632c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
2633951c6300SRichard Henderson {
263459227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2635951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
263659227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
2637951c6300SRichard Henderson #else
2638c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
263959227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2640c45cb8bbSRichard Henderson     } else {
264159227d5dSRichard Henderson         tcg_gen_op3(&tcg_ctx, opc, GET_TCGV_I32(val), GET_TCGV_I64(addr), oi);
2642c45cb8bbSRichard Henderson     }
2643951c6300SRichard Henderson #endif
2644c45cb8bbSRichard Henderson }
2645c45cb8bbSRichard Henderson 
2646c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
2647c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
2648c45cb8bbSRichard Henderson {
264959227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
2650c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
2651c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
265259227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
2653c45cb8bbSRichard Henderson     } else {
265459227d5dSRichard Henderson         tcg_gen_op3(&tcg_ctx, opc, GET_TCGV_I64(val), GET_TCGV_I32(addr), oi);
2655c45cb8bbSRichard Henderson     }
2656c45cb8bbSRichard Henderson #else
2657c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
265859227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
265959227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2660c45cb8bbSRichard Henderson     } else {
266159227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
2662c45cb8bbSRichard Henderson     }
2663c45cb8bbSRichard Henderson #endif
2664c45cb8bbSRichard Henderson }
2665951c6300SRichard Henderson 
2666*b32dc337SPranith Kumar static void tcg_gen_req_mo(TCGBar type)
2667*b32dc337SPranith Kumar {
2668*b32dc337SPranith Kumar #ifdef TCG_GUEST_DEFAULT_MO
2669*b32dc337SPranith Kumar     type &= TCG_GUEST_DEFAULT_MO;
2670*b32dc337SPranith Kumar #endif
2671*b32dc337SPranith Kumar     type &= ~TCG_TARGET_DEFAULT_MO;
2672*b32dc337SPranith Kumar     if (type) {
2673*b32dc337SPranith Kumar         tcg_gen_mb(type | TCG_BAR_SC);
2674*b32dc337SPranith Kumar     }
2675*b32dc337SPranith Kumar }
2676*b32dc337SPranith Kumar 
2677951c6300SRichard Henderson void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2678951c6300SRichard Henderson {
2679*b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
2680951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2681dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
2682dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
2683c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
2684951c6300SRichard Henderson }
2685951c6300SRichard Henderson 
2686951c6300SRichard Henderson void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2687951c6300SRichard Henderson {
2688*b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
2689951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
2690dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
2691dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
2692c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
2693951c6300SRichard Henderson }
2694951c6300SRichard Henderson 
2695951c6300SRichard Henderson void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2696951c6300SRichard Henderson {
2697*b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
26983a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2699951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
2700951c6300SRichard Henderson         if (memop & MO_SIGN) {
2701951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
2702951c6300SRichard Henderson         } else {
2703951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
2704951c6300SRichard Henderson         }
2705951c6300SRichard Henderson         return;
2706951c6300SRichard Henderson     }
2707951c6300SRichard Henderson 
2708c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2709dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
2710dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
2711c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
2712951c6300SRichard Henderson }
2713951c6300SRichard Henderson 
2714951c6300SRichard Henderson void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
2715951c6300SRichard Henderson {
2716*b32dc337SPranith Kumar     tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
27173a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
2718951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
2719951c6300SRichard Henderson         return;
2720951c6300SRichard Henderson     }
2721951c6300SRichard Henderson 
2722c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
2723dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
2724dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
2725c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
2726951c6300SRichard Henderson }
2727c482cb11SRichard Henderson 
2728c482cb11SRichard Henderson static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc)
2729c482cb11SRichard Henderson {
2730c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2731c482cb11SRichard Henderson     case MO_SB:
2732c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
2733c482cb11SRichard Henderson         break;
2734c482cb11SRichard Henderson     case MO_UB:
2735c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
2736c482cb11SRichard Henderson         break;
2737c482cb11SRichard Henderson     case MO_SW:
2738c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
2739c482cb11SRichard Henderson         break;
2740c482cb11SRichard Henderson     case MO_UW:
2741c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
2742c482cb11SRichard Henderson         break;
2743c482cb11SRichard Henderson     default:
2744c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
2745c482cb11SRichard Henderson         break;
2746c482cb11SRichard Henderson     }
2747c482cb11SRichard Henderson }
2748c482cb11SRichard Henderson 
2749c482cb11SRichard Henderson static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, TCGMemOp opc)
2750c482cb11SRichard Henderson {
2751c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2752c482cb11SRichard Henderson     case MO_SB:
2753c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
2754c482cb11SRichard Henderson         break;
2755c482cb11SRichard Henderson     case MO_UB:
2756c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
2757c482cb11SRichard Henderson         break;
2758c482cb11SRichard Henderson     case MO_SW:
2759c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
2760c482cb11SRichard Henderson         break;
2761c482cb11SRichard Henderson     case MO_UW:
2762c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
2763c482cb11SRichard Henderson         break;
2764c482cb11SRichard Henderson     case MO_SL:
2765c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
2766c482cb11SRichard Henderson         break;
2767c482cb11SRichard Henderson     case MO_UL:
2768c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
2769c482cb11SRichard Henderson         break;
2770c482cb11SRichard Henderson     default:
2771c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
2772c482cb11SRichard Henderson         break;
2773c482cb11SRichard Henderson     }
2774c482cb11SRichard Henderson }
2775c482cb11SRichard Henderson 
2776c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2777c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
2778c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
2779c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
2780c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
2781c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
2782c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
2783c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
2784c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
2785c482cb11SRichard Henderson #else
2786c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
2787c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
2788c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
2789c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
2790c482cb11SRichard Henderson #endif
2791c482cb11SRichard Henderson 
2792df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2793df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
2794df79b996SRichard Henderson #else
2795df79b996SRichard Henderson # define WITH_ATOMIC64(X)
2796df79b996SRichard Henderson #endif
2797df79b996SRichard Henderson 
2798c482cb11SRichard Henderson static void * const table_cmpxchg[16] = {
2799c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
2800c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
2801c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
2802c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
2803c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
2804df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
2805df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
2806c482cb11SRichard Henderson };
2807c482cb11SRichard Henderson 
2808c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
2809c482cb11SRichard Henderson                                 TCGv_i32 newv, TCGArg idx, TCGMemOp memop)
2810c482cb11SRichard Henderson {
2811c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2812c482cb11SRichard Henderson 
2813c482cb11SRichard Henderson     if (!parallel_cpus) {
2814c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2815c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
2816c482cb11SRichard Henderson 
2817c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
2818c482cb11SRichard Henderson 
2819c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2820c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
2821c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2822c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
2823c482cb11SRichard Henderson 
2824c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2825c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
2826c482cb11SRichard Henderson         } else {
2827c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
2828c482cb11SRichard Henderson         }
2829c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
2830c482cb11SRichard Henderson     } else {
2831c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
2832c482cb11SRichard Henderson 
2833c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2834c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2835c482cb11SRichard Henderson 
2836c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2837c482cb11SRichard Henderson         {
2838c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2839c482cb11SRichard Henderson             gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv, oi);
2840c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2841c482cb11SRichard Henderson         }
2842c482cb11SRichard Henderson #else
2843c482cb11SRichard Henderson         gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv);
2844c482cb11SRichard Henderson #endif
2845c482cb11SRichard Henderson 
2846c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2847c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
2848c482cb11SRichard Henderson         }
2849c482cb11SRichard Henderson     }
2850c482cb11SRichard Henderson }
2851c482cb11SRichard Henderson 
2852c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
2853c482cb11SRichard Henderson                                 TCGv_i64 newv, TCGArg idx, TCGMemOp memop)
2854c482cb11SRichard Henderson {
2855c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2856c482cb11SRichard Henderson 
2857c482cb11SRichard Henderson     if (!parallel_cpus) {
2858c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2859c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2860c482cb11SRichard Henderson 
2861c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
2862c482cb11SRichard Henderson 
2863c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2864c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
2865c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2866c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
2867c482cb11SRichard Henderson 
2868c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2869c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
2870c482cb11SRichard Henderson         } else {
2871c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
2872c482cb11SRichard Henderson         }
2873c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
2874c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
2875df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2876c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
2877c482cb11SRichard Henderson 
2878c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2879c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2880c482cb11SRichard Henderson 
2881c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2882c482cb11SRichard Henderson         {
2883c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
2884c482cb11SRichard Henderson             gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv, oi);
2885c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2886c482cb11SRichard Henderson         }
2887c482cb11SRichard Henderson #else
2888c482cb11SRichard Henderson         gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv);
2889c482cb11SRichard Henderson #endif
2890df79b996SRichard Henderson #else
2891df79b996SRichard Henderson         gen_helper_exit_atomic(tcg_ctx.tcg_env);
289279b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
289379b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
289479b1af90SRichard Henderson         tcg_gen_movi_i64(retv, 0);
2895df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
2896c482cb11SRichard Henderson     } else {
2897c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
2898c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
2899c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
2900c482cb11SRichard Henderson 
2901c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
2902c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
2903c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
2904c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
2905c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
2906c482cb11SRichard Henderson 
2907c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
2908c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
2909c482cb11SRichard Henderson 
2910c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2911c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
2912c482cb11SRichard Henderson         }
2913c482cb11SRichard Henderson     }
2914c482cb11SRichard Henderson }
2915c482cb11SRichard Henderson 
2916c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2917c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2918c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
2919c482cb11SRichard Henderson {
2920c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
2921c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
2922c482cb11SRichard Henderson 
2923c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2924c482cb11SRichard Henderson 
2925c482cb11SRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2926c482cb11SRichard Henderson     gen(t2, t1, val);
2927c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2928c482cb11SRichard Henderson 
2929c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
2930c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
2931c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
2932c482cb11SRichard Henderson }
2933c482cb11SRichard Henderson 
2934c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2935c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2936c482cb11SRichard Henderson {
2937c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
2938c482cb11SRichard Henderson 
2939c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2940c482cb11SRichard Henderson 
2941c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
2942c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
2943c482cb11SRichard Henderson 
2944c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2945c482cb11SRichard Henderson     {
2946c482cb11SRichard Henderson         TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2947c482cb11SRichard Henderson         gen(ret, tcg_ctx.tcg_env, addr, val, oi);
2948c482cb11SRichard Henderson         tcg_temp_free_i32(oi);
2949c482cb11SRichard Henderson     }
2950c482cb11SRichard Henderson #else
2951c482cb11SRichard Henderson     gen(ret, tcg_ctx.tcg_env, addr, val);
2952c482cb11SRichard Henderson #endif
2953c482cb11SRichard Henderson 
2954c482cb11SRichard Henderson     if (memop & MO_SIGN) {
2955c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
2956c482cb11SRichard Henderson     }
2957c482cb11SRichard Henderson }
2958c482cb11SRichard Henderson 
2959c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2960c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2961c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
2962c482cb11SRichard Henderson {
2963c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
2964c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
2965c482cb11SRichard Henderson 
2966c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2967c482cb11SRichard Henderson 
2968c482cb11SRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2969c482cb11SRichard Henderson     gen(t2, t1, val);
2970c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2971c482cb11SRichard Henderson 
2972c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
2973c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
2974c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
2975c482cb11SRichard Henderson }
2976c482cb11SRichard Henderson 
2977c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2978c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2979c482cb11SRichard Henderson {
2980c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2981c482cb11SRichard Henderson 
2982c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
2983df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2984c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
2985c482cb11SRichard Henderson 
2986c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
2987c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2988c482cb11SRichard Henderson 
2989c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2990c482cb11SRichard Henderson         {
2991c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2992c482cb11SRichard Henderson             gen(ret, tcg_ctx.tcg_env, addr, val, oi);
2993c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2994c482cb11SRichard Henderson         }
2995c482cb11SRichard Henderson #else
2996c482cb11SRichard Henderson         gen(ret, tcg_ctx.tcg_env, addr, val);
2997c482cb11SRichard Henderson #endif
2998df79b996SRichard Henderson #else
2999df79b996SRichard Henderson         gen_helper_exit_atomic(tcg_ctx.tcg_env);
300079b1af90SRichard Henderson         /* Produce a result, so that we have a well-formed opcode stream
300179b1af90SRichard Henderson            with respect to uses of the result in the (dead) code following.  */
300279b1af90SRichard Henderson         tcg_gen_movi_i64(ret, 0);
3003df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
3004c482cb11SRichard Henderson     } else {
3005c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
3006c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
3007c482cb11SRichard Henderson 
3008c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
3009c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
3010c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
3011c482cb11SRichard Henderson 
3012c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
3013c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
3014c482cb11SRichard Henderson 
3015c482cb11SRichard Henderson         if (memop & MO_SIGN) {
3016c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
3017c482cb11SRichard Henderson         }
3018c482cb11SRichard Henderson     }
3019c482cb11SRichard Henderson }
3020c482cb11SRichard Henderson 
3021c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
3022c482cb11SRichard Henderson static void * const table_##NAME[16] = {                                \
3023c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
3024c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
3025c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
3026c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
3027c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
3028df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
3029df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
3030c482cb11SRichard Henderson };                                                                      \
3031c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
3032c482cb11SRichard Henderson     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \
3033c482cb11SRichard Henderson {                                                                       \
3034c482cb11SRichard Henderson     if (parallel_cpus) {                                                \
3035c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
3036c482cb11SRichard Henderson     } else {                                                            \
3037c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
3038c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
3039c482cb11SRichard Henderson     }                                                                   \
3040c482cb11SRichard Henderson }                                                                       \
3041c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
3042c482cb11SRichard Henderson     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \
3043c482cb11SRichard Henderson {                                                                       \
3044c482cb11SRichard Henderson     if (parallel_cpus) {                                                \
3045c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
3046c482cb11SRichard Henderson     } else {                                                            \
3047c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
3048c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
3049c482cb11SRichard Henderson     }                                                                   \
3050c482cb11SRichard Henderson }
3051c482cb11SRichard Henderson 
3052c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
3053c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
3054c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
3055c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
3056c482cb11SRichard Henderson 
3057c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
3058c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
3059c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
3060c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
3061c482cb11SRichard Henderson 
3062c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
3063c482cb11SRichard Henderson {
3064c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
3065c482cb11SRichard Henderson }
3066c482cb11SRichard Henderson 
3067c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
3068c482cb11SRichard Henderson {
3069c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
3070c482cb11SRichard Henderson }
3071c482cb11SRichard Henderson 
3072c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
3073c482cb11SRichard Henderson 
3074c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
3075