xref: /openbmc/qemu/tcg/tcg-op.c (revision df79b996)
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"
31dcdaadb6SLluís Vilanova #include "trace-tcg.h"
32dcdaadb6SLluís Vilanova #include "trace/mem.h"
33951c6300SRichard Henderson 
343a13c3f3SRichard Henderson /* Reduce the number of ifdefs below.  This assumes that all uses of
353a13c3f3SRichard Henderson    TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
363a13c3f3SRichard Henderson    the compiler can eliminate.  */
373a13c3f3SRichard Henderson #if TCG_TARGET_REG_BITS == 64
383a13c3f3SRichard Henderson extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
393a13c3f3SRichard Henderson extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
403a13c3f3SRichard Henderson #define TCGV_LOW  TCGV_LOW_link_error
413a13c3f3SRichard Henderson #define TCGV_HIGH TCGV_HIGH_link_error
423a13c3f3SRichard Henderson #endif
43951c6300SRichard Henderson 
44c45cb8bbSRichard Henderson /* Note that this is optimized for sequential allocation during translate.
45c45cb8bbSRichard Henderson    Up to and including filling in the forward link immediately.  We'll do
46c45cb8bbSRichard Henderson    proper termination of the end of the list after we finish translation.  */
47c45cb8bbSRichard Henderson 
48c45cb8bbSRichard Henderson static void tcg_emit_op(TCGContext *ctx, TCGOpcode opc, int args)
49c45cb8bbSRichard Henderson {
50c45cb8bbSRichard Henderson     int oi = ctx->gen_next_op_idx;
51c45cb8bbSRichard Henderson     int ni = oi + 1;
52c45cb8bbSRichard Henderson     int pi = oi - 1;
53c45cb8bbSRichard Henderson 
54c45cb8bbSRichard Henderson     tcg_debug_assert(oi < OPC_BUF_SIZE);
55dcb8e758SRichard Henderson     ctx->gen_op_buf[0].prev = oi;
56c45cb8bbSRichard Henderson     ctx->gen_next_op_idx = ni;
57c45cb8bbSRichard Henderson 
58c45cb8bbSRichard Henderson     ctx->gen_op_buf[oi] = (TCGOp){
59c45cb8bbSRichard Henderson         .opc = opc,
60c45cb8bbSRichard Henderson         .args = args,
61c45cb8bbSRichard Henderson         .prev = pi,
62c45cb8bbSRichard Henderson         .next = ni
63c45cb8bbSRichard Henderson     };
64c45cb8bbSRichard Henderson }
65c45cb8bbSRichard Henderson 
66951c6300SRichard Henderson void tcg_gen_op1(TCGContext *ctx, TCGOpcode opc, TCGArg a1)
67951c6300SRichard Henderson {
68c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
69951c6300SRichard Henderson 
70c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 1 <= OPPARAM_BUF_SIZE);
71c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 1;
72c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi] = a1;
73951c6300SRichard Henderson 
74c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
75951c6300SRichard Henderson }
76951c6300SRichard Henderson 
77951c6300SRichard Henderson void tcg_gen_op2(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2)
78951c6300SRichard Henderson {
79c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
80951c6300SRichard Henderson 
81c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 2 <= OPPARAM_BUF_SIZE);
82c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 2;
83c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
84c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
85951c6300SRichard Henderson 
86c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
87951c6300SRichard Henderson }
88951c6300SRichard Henderson 
89951c6300SRichard Henderson void tcg_gen_op3(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
90951c6300SRichard Henderson                  TCGArg a2, TCGArg a3)
91951c6300SRichard Henderson {
92c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
93951c6300SRichard Henderson 
94c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 3 <= OPPARAM_BUF_SIZE);
95c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 3;
96c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
97c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
98c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
99951c6300SRichard Henderson 
100c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
101951c6300SRichard Henderson }
102951c6300SRichard Henderson 
103951c6300SRichard Henderson void tcg_gen_op4(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
104951c6300SRichard Henderson                  TCGArg a2, TCGArg a3, TCGArg a4)
105951c6300SRichard Henderson {
106c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
107951c6300SRichard Henderson 
108c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 4 <= OPPARAM_BUF_SIZE);
109c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 4;
110c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
111c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
112c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
113c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 3] = a4;
114951c6300SRichard Henderson 
115c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
116951c6300SRichard Henderson }
117951c6300SRichard Henderson 
118951c6300SRichard Henderson void tcg_gen_op5(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
119951c6300SRichard Henderson                  TCGArg a2, TCGArg a3, TCGArg a4, TCGArg a5)
120951c6300SRichard Henderson {
121c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
122951c6300SRichard Henderson 
123c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 5 <= OPPARAM_BUF_SIZE);
124c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 5;
125c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
126c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
127c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
128c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 3] = a4;
129c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 4] = a5;
130951c6300SRichard Henderson 
131c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
132951c6300SRichard Henderson }
133951c6300SRichard Henderson 
134951c6300SRichard Henderson void tcg_gen_op6(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2,
135951c6300SRichard Henderson                  TCGArg a3, TCGArg a4, TCGArg a5, TCGArg a6)
136951c6300SRichard Henderson {
137c45cb8bbSRichard Henderson     int pi = ctx->gen_next_parm_idx;
138951c6300SRichard Henderson 
139c45cb8bbSRichard Henderson     tcg_debug_assert(pi + 6 <= OPPARAM_BUF_SIZE);
140c45cb8bbSRichard Henderson     ctx->gen_next_parm_idx = pi + 6;
141c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 0] = a1;
142c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 1] = a2;
143c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 2] = a3;
144c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 3] = a4;
145c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 4] = a5;
146c45cb8bbSRichard Henderson     ctx->gen_opparam_buf[pi + 5] = a6;
147951c6300SRichard Henderson 
148c45cb8bbSRichard Henderson     tcg_emit_op(ctx, opc, pi);
149951c6300SRichard Henderson }
150951c6300SRichard Henderson 
151f65e19bcSPranith Kumar void tcg_gen_mb(TCGBar mb_type)
152f65e19bcSPranith Kumar {
153f65e19bcSPranith Kumar     bool emit_barriers = true;
154f65e19bcSPranith Kumar 
155f65e19bcSPranith Kumar #ifndef CONFIG_USER_ONLY
156f65e19bcSPranith Kumar     /* TODO: When MTTCG is available for system mode, we will check
157f65e19bcSPranith Kumar      * the following condition and enable emit_barriers
158f65e19bcSPranith Kumar      * (qemu_tcg_mttcg_enabled() && smp_cpus > 1)
159f65e19bcSPranith Kumar      */
160f65e19bcSPranith Kumar     emit_barriers = false;
161f65e19bcSPranith Kumar #endif
162f65e19bcSPranith Kumar 
163f65e19bcSPranith Kumar     if (emit_barriers) {
164f65e19bcSPranith Kumar         tcg_gen_op1(&tcg_ctx, INDEX_op_mb, mb_type);
165f65e19bcSPranith Kumar     }
166f65e19bcSPranith Kumar }
167f65e19bcSPranith Kumar 
168951c6300SRichard Henderson /* 32 bit ops */
169951c6300SRichard Henderson 
170951c6300SRichard Henderson void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
171951c6300SRichard Henderson {
172951c6300SRichard Henderson     /* some cases can be optimized here */
173951c6300SRichard Henderson     if (arg2 == 0) {
174951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
175951c6300SRichard Henderson     } else {
176951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
177951c6300SRichard Henderson         tcg_gen_add_i32(ret, arg1, t0);
178951c6300SRichard Henderson         tcg_temp_free_i32(t0);
179951c6300SRichard Henderson     }
180951c6300SRichard Henderson }
181951c6300SRichard Henderson 
182951c6300SRichard Henderson void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
183951c6300SRichard Henderson {
184951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
185951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i32.  */
186951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
187951c6300SRichard Henderson     } else {
188951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg1);
189951c6300SRichard Henderson         tcg_gen_sub_i32(ret, t0, arg2);
190951c6300SRichard Henderson         tcg_temp_free_i32(t0);
191951c6300SRichard Henderson     }
192951c6300SRichard Henderson }
193951c6300SRichard Henderson 
194951c6300SRichard Henderson void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
195951c6300SRichard Henderson {
196951c6300SRichard Henderson     /* some cases can be optimized here */
197951c6300SRichard Henderson     if (arg2 == 0) {
198951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
199951c6300SRichard Henderson     } else {
200951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
201951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
202951c6300SRichard Henderson         tcg_temp_free_i32(t0);
203951c6300SRichard Henderson     }
204951c6300SRichard Henderson }
205951c6300SRichard Henderson 
206951c6300SRichard Henderson void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
207951c6300SRichard Henderson {
208951c6300SRichard Henderson     TCGv_i32 t0;
209951c6300SRichard Henderson     /* Some cases can be optimized here.  */
210951c6300SRichard Henderson     switch (arg2) {
211951c6300SRichard Henderson     case 0:
212951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
213951c6300SRichard Henderson         return;
214951c6300SRichard Henderson     case 0xffffffffu:
215951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
216951c6300SRichard Henderson         return;
217951c6300SRichard Henderson     case 0xffu:
218951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i32.  */
219951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i32) {
220951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
221951c6300SRichard Henderson             return;
222951c6300SRichard Henderson         }
223951c6300SRichard Henderson         break;
224951c6300SRichard Henderson     case 0xffffu:
225951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i32) {
226951c6300SRichard Henderson             tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
227951c6300SRichard Henderson             return;
228951c6300SRichard Henderson         }
229951c6300SRichard Henderson         break;
230951c6300SRichard Henderson     }
231951c6300SRichard Henderson     t0 = tcg_const_i32(arg2);
232951c6300SRichard Henderson     tcg_gen_and_i32(ret, arg1, t0);
233951c6300SRichard Henderson     tcg_temp_free_i32(t0);
234951c6300SRichard Henderson }
235951c6300SRichard Henderson 
236951c6300SRichard Henderson void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
237951c6300SRichard Henderson {
238951c6300SRichard Henderson     /* Some cases can be optimized here.  */
239951c6300SRichard Henderson     if (arg2 == -1) {
240951c6300SRichard Henderson         tcg_gen_movi_i32(ret, -1);
241951c6300SRichard Henderson     } else if (arg2 == 0) {
242951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
243951c6300SRichard Henderson     } else {
244951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
245951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
246951c6300SRichard Henderson         tcg_temp_free_i32(t0);
247951c6300SRichard Henderson     }
248951c6300SRichard Henderson }
249951c6300SRichard Henderson 
250951c6300SRichard Henderson void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
251951c6300SRichard Henderson {
252951c6300SRichard Henderson     /* Some cases can be optimized here.  */
253951c6300SRichard Henderson     if (arg2 == 0) {
254951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
255951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
256951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i32.  */
257951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
258951c6300SRichard Henderson     } else {
259951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
260951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, t0);
261951c6300SRichard Henderson         tcg_temp_free_i32(t0);
262951c6300SRichard Henderson     }
263951c6300SRichard Henderson }
264951c6300SRichard Henderson 
265951c6300SRichard Henderson void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
266951c6300SRichard Henderson {
267951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
268951c6300SRichard Henderson     if (arg2 == 0) {
269951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
270951c6300SRichard Henderson     } else {
271951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
272951c6300SRichard Henderson         tcg_gen_shl_i32(ret, arg1, t0);
273951c6300SRichard Henderson         tcg_temp_free_i32(t0);
274951c6300SRichard Henderson     }
275951c6300SRichard Henderson }
276951c6300SRichard Henderson 
277951c6300SRichard Henderson void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
278951c6300SRichard Henderson {
279951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
280951c6300SRichard Henderson     if (arg2 == 0) {
281951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
282951c6300SRichard Henderson     } else {
283951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
284951c6300SRichard Henderson         tcg_gen_shr_i32(ret, arg1, t0);
285951c6300SRichard Henderson         tcg_temp_free_i32(t0);
286951c6300SRichard Henderson     }
287951c6300SRichard Henderson }
288951c6300SRichard Henderson 
289951c6300SRichard Henderson void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
290951c6300SRichard Henderson {
291951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
292951c6300SRichard Henderson     if (arg2 == 0) {
293951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
294951c6300SRichard Henderson     } else {
295951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
296951c6300SRichard Henderson         tcg_gen_sar_i32(ret, arg1, t0);
297951c6300SRichard Henderson         tcg_temp_free_i32(t0);
298951c6300SRichard Henderson     }
299951c6300SRichard Henderson }
300951c6300SRichard Henderson 
30142a268c2SRichard Henderson void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
302951c6300SRichard Henderson {
303951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
30442a268c2SRichard Henderson         tcg_gen_br(l);
305951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
30642a268c2SRichard Henderson         tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
307951c6300SRichard Henderson     }
308951c6300SRichard Henderson }
309951c6300SRichard Henderson 
31042a268c2SRichard Henderson void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
311951c6300SRichard Henderson {
31237ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
31337ed3bf1SRichard Henderson         tcg_gen_br(l);
31437ed3bf1SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
315951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
31642a268c2SRichard Henderson         tcg_gen_brcond_i32(cond, arg1, t0, l);
317951c6300SRichard Henderson         tcg_temp_free_i32(t0);
318951c6300SRichard Henderson     }
31937ed3bf1SRichard Henderson }
320951c6300SRichard Henderson 
321951c6300SRichard Henderson void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
322951c6300SRichard Henderson                          TCGv_i32 arg1, TCGv_i32 arg2)
323951c6300SRichard Henderson {
324951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
325951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 1);
326951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
327951c6300SRichard Henderson         tcg_gen_movi_i32(ret, 0);
328951c6300SRichard Henderson     } else {
329951c6300SRichard Henderson         tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
330951c6300SRichard Henderson     }
331951c6300SRichard Henderson }
332951c6300SRichard Henderson 
333951c6300SRichard Henderson void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
334951c6300SRichard Henderson                           TCGv_i32 arg1, int32_t arg2)
335951c6300SRichard Henderson {
336951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
337951c6300SRichard Henderson     tcg_gen_setcond_i32(cond, ret, arg1, t0);
338951c6300SRichard Henderson     tcg_temp_free_i32(t0);
339951c6300SRichard Henderson }
340951c6300SRichard Henderson 
341951c6300SRichard Henderson void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
342951c6300SRichard Henderson {
343951c6300SRichard Henderson     TCGv_i32 t0 = tcg_const_i32(arg2);
344951c6300SRichard Henderson     tcg_gen_mul_i32(ret, arg1, t0);
345951c6300SRichard Henderson     tcg_temp_free_i32(t0);
346951c6300SRichard Henderson }
347951c6300SRichard Henderson 
348951c6300SRichard Henderson void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
349951c6300SRichard Henderson {
350951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
351951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
352951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
353951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
354951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
355951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
356951c6300SRichard Henderson         tcg_temp_free_i32(t0);
357951c6300SRichard Henderson     } else {
358951c6300SRichard Henderson         gen_helper_div_i32(ret, arg1, arg2);
359951c6300SRichard Henderson     }
360951c6300SRichard Henderson }
361951c6300SRichard Henderson 
362951c6300SRichard Henderson void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
363951c6300SRichard Henderson {
364951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
365951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
366951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
367951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
368951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
369951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
370951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
371951c6300SRichard Henderson         tcg_temp_free_i32(t0);
372951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
373951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
374951c6300SRichard Henderson         tcg_gen_sari_i32(t0, arg1, 31);
375951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
376951c6300SRichard Henderson         tcg_temp_free_i32(t0);
377951c6300SRichard Henderson     } else {
378951c6300SRichard Henderson         gen_helper_rem_i32(ret, arg1, arg2);
379951c6300SRichard Henderson     }
380951c6300SRichard Henderson }
381951c6300SRichard Henderson 
382951c6300SRichard Henderson void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
383951c6300SRichard Henderson {
384951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i32) {
385951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
386951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
387951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
388951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
389951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
390951c6300SRichard Henderson         tcg_temp_free_i32(t0);
391951c6300SRichard Henderson     } else {
392951c6300SRichard Henderson         gen_helper_divu_i32(ret, arg1, arg2);
393951c6300SRichard Henderson     }
394951c6300SRichard Henderson }
395951c6300SRichard Henderson 
396951c6300SRichard Henderson void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
397951c6300SRichard Henderson {
398951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i32) {
399951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
400951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i32) {
401951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
402951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
403951c6300SRichard Henderson         tcg_gen_mul_i32(t0, t0, arg2);
404951c6300SRichard Henderson         tcg_gen_sub_i32(ret, arg1, t0);
405951c6300SRichard Henderson         tcg_temp_free_i32(t0);
406951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i32) {
407951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
408951c6300SRichard Henderson         tcg_gen_movi_i32(t0, 0);
409951c6300SRichard Henderson         tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
410951c6300SRichard Henderson         tcg_temp_free_i32(t0);
411951c6300SRichard Henderson     } else {
412951c6300SRichard Henderson         gen_helper_remu_i32(ret, arg1, arg2);
413951c6300SRichard Henderson     }
414951c6300SRichard Henderson }
415951c6300SRichard Henderson 
416951c6300SRichard Henderson void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
417951c6300SRichard Henderson {
418951c6300SRichard Henderson     if (TCG_TARGET_HAS_andc_i32) {
419951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
420951c6300SRichard Henderson     } else {
421951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
422951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
423951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, t0);
424951c6300SRichard Henderson         tcg_temp_free_i32(t0);
425951c6300SRichard Henderson     }
426951c6300SRichard Henderson }
427951c6300SRichard Henderson 
428951c6300SRichard Henderson void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
429951c6300SRichard Henderson {
430951c6300SRichard Henderson     if (TCG_TARGET_HAS_eqv_i32) {
431951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
432951c6300SRichard Henderson     } else {
433951c6300SRichard Henderson         tcg_gen_xor_i32(ret, arg1, arg2);
434951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
435951c6300SRichard Henderson     }
436951c6300SRichard Henderson }
437951c6300SRichard Henderson 
438951c6300SRichard Henderson void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
439951c6300SRichard Henderson {
440951c6300SRichard Henderson     if (TCG_TARGET_HAS_nand_i32) {
441951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
442951c6300SRichard Henderson     } else {
443951c6300SRichard Henderson         tcg_gen_and_i32(ret, arg1, arg2);
444951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
445951c6300SRichard Henderson     }
446951c6300SRichard Henderson }
447951c6300SRichard Henderson 
448951c6300SRichard Henderson void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
449951c6300SRichard Henderson {
450951c6300SRichard Henderson     if (TCG_TARGET_HAS_nor_i32) {
451951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
452951c6300SRichard Henderson     } else {
453951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, arg2);
454951c6300SRichard Henderson         tcg_gen_not_i32(ret, ret);
455951c6300SRichard Henderson     }
456951c6300SRichard Henderson }
457951c6300SRichard Henderson 
458951c6300SRichard Henderson void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
459951c6300SRichard Henderson {
460951c6300SRichard Henderson     if (TCG_TARGET_HAS_orc_i32) {
461951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
462951c6300SRichard Henderson     } else {
463951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
464951c6300SRichard Henderson         tcg_gen_not_i32(t0, arg2);
465951c6300SRichard Henderson         tcg_gen_or_i32(ret, arg1, t0);
466951c6300SRichard Henderson         tcg_temp_free_i32(t0);
467951c6300SRichard Henderson     }
468951c6300SRichard Henderson }
469951c6300SRichard Henderson 
470951c6300SRichard Henderson void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
471951c6300SRichard Henderson {
472951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
473951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
474951c6300SRichard Henderson     } else {
475951c6300SRichard Henderson         TCGv_i32 t0, t1;
476951c6300SRichard Henderson 
477951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
478951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
479951c6300SRichard Henderson         tcg_gen_shl_i32(t0, arg1, arg2);
480951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
481951c6300SRichard Henderson         tcg_gen_shr_i32(t1, arg1, t1);
482951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
483951c6300SRichard Henderson         tcg_temp_free_i32(t0);
484951c6300SRichard Henderson         tcg_temp_free_i32(t1);
485951c6300SRichard Henderson     }
486951c6300SRichard Henderson }
487951c6300SRichard Henderson 
488951c6300SRichard Henderson void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
489951c6300SRichard Henderson {
490951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
491951c6300SRichard Henderson     /* some cases can be optimized here */
492951c6300SRichard Henderson     if (arg2 == 0) {
493951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
494951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i32) {
495951c6300SRichard Henderson         TCGv_i32 t0 = tcg_const_i32(arg2);
496951c6300SRichard Henderson         tcg_gen_rotl_i32(ret, arg1, t0);
497951c6300SRichard Henderson         tcg_temp_free_i32(t0);
498951c6300SRichard Henderson     } else {
499951c6300SRichard Henderson         TCGv_i32 t0, t1;
500951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
501951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
502951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg1, arg2);
503951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg1, 32 - arg2);
504951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
505951c6300SRichard Henderson         tcg_temp_free_i32(t0);
506951c6300SRichard Henderson         tcg_temp_free_i32(t1);
507951c6300SRichard Henderson     }
508951c6300SRichard Henderson }
509951c6300SRichard Henderson 
510951c6300SRichard Henderson void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
511951c6300SRichard Henderson {
512951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i32) {
513951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
514951c6300SRichard Henderson     } else {
515951c6300SRichard Henderson         TCGv_i32 t0, t1;
516951c6300SRichard Henderson 
517951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
518951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
519951c6300SRichard Henderson         tcg_gen_shr_i32(t0, arg1, arg2);
520951c6300SRichard Henderson         tcg_gen_subfi_i32(t1, 32, arg2);
521951c6300SRichard Henderson         tcg_gen_shl_i32(t1, arg1, t1);
522951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
523951c6300SRichard Henderson         tcg_temp_free_i32(t0);
524951c6300SRichard Henderson         tcg_temp_free_i32(t1);
525951c6300SRichard Henderson     }
526951c6300SRichard Henderson }
527951c6300SRichard Henderson 
528951c6300SRichard Henderson void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
529951c6300SRichard Henderson {
530951c6300SRichard Henderson     tcg_debug_assert(arg2 < 32);
531951c6300SRichard Henderson     /* some cases can be optimized here */
532951c6300SRichard Henderson     if (arg2 == 0) {
533951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg1);
534951c6300SRichard Henderson     } else {
535951c6300SRichard Henderson         tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
536951c6300SRichard Henderson     }
537951c6300SRichard Henderson }
538951c6300SRichard Henderson 
539951c6300SRichard Henderson void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
540951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
541951c6300SRichard Henderson {
542951c6300SRichard Henderson     uint32_t mask;
543951c6300SRichard Henderson     TCGv_i32 t1;
544951c6300SRichard Henderson 
545951c6300SRichard Henderson     tcg_debug_assert(ofs < 32);
546951c6300SRichard Henderson     tcg_debug_assert(len <= 32);
547951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 32);
548951c6300SRichard Henderson 
549951c6300SRichard Henderson     if (ofs == 0 && len == 32) {
550951c6300SRichard Henderson         tcg_gen_mov_i32(ret, arg2);
551951c6300SRichard Henderson         return;
552951c6300SRichard Henderson     }
553951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
554951c6300SRichard Henderson         tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
555951c6300SRichard Henderson         return;
556951c6300SRichard Henderson     }
557951c6300SRichard Henderson 
558951c6300SRichard Henderson     mask = (1u << len) - 1;
559951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
560951c6300SRichard Henderson 
561951c6300SRichard Henderson     if (ofs + len < 32) {
562951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg2, mask);
563951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, ofs);
564951c6300SRichard Henderson     } else {
565951c6300SRichard Henderson         tcg_gen_shli_i32(t1, arg2, ofs);
566951c6300SRichard Henderson     }
567951c6300SRichard Henderson     tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
568951c6300SRichard Henderson     tcg_gen_or_i32(ret, ret, t1);
569951c6300SRichard Henderson 
570951c6300SRichard Henderson     tcg_temp_free_i32(t1);
571951c6300SRichard Henderson }
572951c6300SRichard Henderson 
573951c6300SRichard Henderson void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
574951c6300SRichard Henderson                          TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
575951c6300SRichard Henderson {
57637ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
57737ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v1);
57837ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
57937ed3bf1SRichard Henderson         tcg_gen_mov_i32(ret, v2);
58037ed3bf1SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i32) {
581951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
582951c6300SRichard Henderson     } else {
583951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
584951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
585951c6300SRichard Henderson         tcg_gen_setcond_i32(cond, t0, c1, c2);
586951c6300SRichard Henderson         tcg_gen_neg_i32(t0, t0);
587951c6300SRichard Henderson         tcg_gen_and_i32(t1, v1, t0);
588951c6300SRichard Henderson         tcg_gen_andc_i32(ret, v2, t0);
589951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t1);
590951c6300SRichard Henderson         tcg_temp_free_i32(t0);
591951c6300SRichard Henderson         tcg_temp_free_i32(t1);
592951c6300SRichard Henderson     }
593951c6300SRichard Henderson }
594951c6300SRichard Henderson 
595951c6300SRichard Henderson void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
596951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
597951c6300SRichard Henderson {
598951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i32) {
599951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
600951c6300SRichard Henderson     } else {
601951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
602951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
603951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
604951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
605951c6300SRichard Henderson         tcg_gen_add_i64(t0, t0, t1);
606951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
607951c6300SRichard Henderson         tcg_temp_free_i64(t0);
608951c6300SRichard Henderson         tcg_temp_free_i64(t1);
609951c6300SRichard Henderson     }
610951c6300SRichard Henderson }
611951c6300SRichard Henderson 
612951c6300SRichard Henderson void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
613951c6300SRichard Henderson                       TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
614951c6300SRichard Henderson {
615951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i32) {
616951c6300SRichard Henderson         tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
617951c6300SRichard Henderson     } else {
618951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
619951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
620951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t0, al, ah);
621951c6300SRichard Henderson         tcg_gen_concat_i32_i64(t1, bl, bh);
622951c6300SRichard Henderson         tcg_gen_sub_i64(t0, t0, t1);
623951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
624951c6300SRichard Henderson         tcg_temp_free_i64(t0);
625951c6300SRichard Henderson         tcg_temp_free_i64(t1);
626951c6300SRichard Henderson     }
627951c6300SRichard Henderson }
628951c6300SRichard Henderson 
629951c6300SRichard Henderson void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
630951c6300SRichard Henderson {
631951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i32) {
632951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
633951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i32) {
634951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
635951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
636951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
637951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
638951c6300SRichard Henderson         tcg_temp_free_i32(t);
639951c6300SRichard Henderson     } else {
640951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
641951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
642951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t0, arg1);
643951c6300SRichard Henderson         tcg_gen_extu_i32_i64(t1, arg2);
644951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
645951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
646951c6300SRichard Henderson         tcg_temp_free_i64(t0);
647951c6300SRichard Henderson         tcg_temp_free_i64(t1);
648951c6300SRichard Henderson     }
649951c6300SRichard Henderson }
650951c6300SRichard Henderson 
651951c6300SRichard Henderson void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
652951c6300SRichard Henderson {
653951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i32) {
654951c6300SRichard Henderson         tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
655951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i32) {
656951c6300SRichard Henderson         TCGv_i32 t = tcg_temp_new_i32();
657951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
658951c6300SRichard Henderson         tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
659951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t);
660951c6300SRichard Henderson         tcg_temp_free_i32(t);
661951c6300SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
662951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
663951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
664951c6300SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
665951c6300SRichard Henderson         TCGv_i32 t3 = tcg_temp_new_i32();
666951c6300SRichard Henderson         tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
667951c6300SRichard Henderson         /* Adjust for negative inputs.  */
668951c6300SRichard Henderson         tcg_gen_sari_i32(t2, arg1, 31);
669951c6300SRichard Henderson         tcg_gen_sari_i32(t3, arg2, 31);
670951c6300SRichard Henderson         tcg_gen_and_i32(t2, t2, arg2);
671951c6300SRichard Henderson         tcg_gen_and_i32(t3, t3, arg1);
672951c6300SRichard Henderson         tcg_gen_sub_i32(rh, t1, t2);
673951c6300SRichard Henderson         tcg_gen_sub_i32(rh, rh, t3);
674951c6300SRichard Henderson         tcg_gen_mov_i32(rl, t0);
675951c6300SRichard Henderson         tcg_temp_free_i32(t0);
676951c6300SRichard Henderson         tcg_temp_free_i32(t1);
677951c6300SRichard Henderson         tcg_temp_free_i32(t2);
678951c6300SRichard Henderson         tcg_temp_free_i32(t3);
679951c6300SRichard Henderson     } else {
680951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
681951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
682951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t0, arg1);
683951c6300SRichard Henderson         tcg_gen_ext_i32_i64(t1, arg2);
684951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, t1);
685951c6300SRichard Henderson         tcg_gen_extr_i64_i32(rl, rh, t0);
686951c6300SRichard Henderson         tcg_temp_free_i64(t0);
687951c6300SRichard Henderson         tcg_temp_free_i64(t1);
688951c6300SRichard Henderson     }
689951c6300SRichard Henderson }
690951c6300SRichard Henderson 
691951c6300SRichard Henderson void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
692951c6300SRichard Henderson {
693951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8s_i32) {
694951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
695951c6300SRichard Henderson     } else {
696951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 24);
697951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 24);
698951c6300SRichard Henderson     }
699951c6300SRichard Henderson }
700951c6300SRichard Henderson 
701951c6300SRichard Henderson void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
702951c6300SRichard Henderson {
703951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16s_i32) {
704951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
705951c6300SRichard Henderson     } else {
706951c6300SRichard Henderson         tcg_gen_shli_i32(ret, arg, 16);
707951c6300SRichard Henderson         tcg_gen_sari_i32(ret, ret, 16);
708951c6300SRichard Henderson     }
709951c6300SRichard Henderson }
710951c6300SRichard Henderson 
711951c6300SRichard Henderson void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
712951c6300SRichard Henderson {
713951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext8u_i32) {
714951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
715951c6300SRichard Henderson     } else {
716951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffu);
717951c6300SRichard Henderson     }
718951c6300SRichard Henderson }
719951c6300SRichard Henderson 
720951c6300SRichard Henderson void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
721951c6300SRichard Henderson {
722951c6300SRichard Henderson     if (TCG_TARGET_HAS_ext16u_i32) {
723951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
724951c6300SRichard Henderson     } else {
725951c6300SRichard Henderson         tcg_gen_andi_i32(ret, arg, 0xffffu);
726951c6300SRichard Henderson     }
727951c6300SRichard Henderson }
728951c6300SRichard Henderson 
729951c6300SRichard Henderson /* Note: we assume the two high bytes are set to zero */
730951c6300SRichard Henderson void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
731951c6300SRichard Henderson {
732951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap16_i32) {
733951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
734951c6300SRichard Henderson     } else {
735951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
736951c6300SRichard Henderson 
737951c6300SRichard Henderson         tcg_gen_ext8u_i32(t0, arg);
738951c6300SRichard Henderson         tcg_gen_shli_i32(t0, t0, 8);
739951c6300SRichard Henderson         tcg_gen_shri_i32(ret, arg, 8);
740951c6300SRichard Henderson         tcg_gen_or_i32(ret, ret, t0);
741951c6300SRichard Henderson         tcg_temp_free_i32(t0);
742951c6300SRichard Henderson     }
743951c6300SRichard Henderson }
744951c6300SRichard Henderson 
745951c6300SRichard Henderson void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
746951c6300SRichard Henderson {
747951c6300SRichard Henderson     if (TCG_TARGET_HAS_bswap32_i32) {
748951c6300SRichard Henderson         tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
749951c6300SRichard Henderson     } else {
750951c6300SRichard Henderson         TCGv_i32 t0, t1;
751951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
752951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
753951c6300SRichard Henderson 
754951c6300SRichard Henderson         tcg_gen_shli_i32(t0, arg, 24);
755951c6300SRichard Henderson 
756951c6300SRichard Henderson         tcg_gen_andi_i32(t1, arg, 0x0000ff00);
757951c6300SRichard Henderson         tcg_gen_shli_i32(t1, t1, 8);
758951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
759951c6300SRichard Henderson 
760951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 8);
761951c6300SRichard Henderson         tcg_gen_andi_i32(t1, t1, 0x0000ff00);
762951c6300SRichard Henderson         tcg_gen_or_i32(t0, t0, t1);
763951c6300SRichard Henderson 
764951c6300SRichard Henderson         tcg_gen_shri_i32(t1, arg, 24);
765951c6300SRichard Henderson         tcg_gen_or_i32(ret, t0, t1);
766951c6300SRichard Henderson         tcg_temp_free_i32(t0);
767951c6300SRichard Henderson         tcg_temp_free_i32(t1);
768951c6300SRichard Henderson     }
769951c6300SRichard Henderson }
770951c6300SRichard Henderson 
771951c6300SRichard Henderson /* 64-bit ops */
772951c6300SRichard Henderson 
773951c6300SRichard Henderson #if TCG_TARGET_REG_BITS == 32
774951c6300SRichard Henderson /* These are all inline for TCG_TARGET_REG_BITS == 64.  */
775951c6300SRichard Henderson 
776951c6300SRichard Henderson void tcg_gen_discard_i64(TCGv_i64 arg)
777951c6300SRichard Henderson {
778951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_LOW(arg));
779951c6300SRichard Henderson     tcg_gen_discard_i32(TCGV_HIGH(arg));
780951c6300SRichard Henderson }
781951c6300SRichard Henderson 
782951c6300SRichard Henderson void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
783951c6300SRichard Henderson {
784951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
785951c6300SRichard Henderson     tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
786951c6300SRichard Henderson }
787951c6300SRichard Henderson 
788951c6300SRichard Henderson void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
789951c6300SRichard Henderson {
790951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_LOW(ret), arg);
791951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
792951c6300SRichard Henderson }
793951c6300SRichard Henderson 
794951c6300SRichard Henderson void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
795951c6300SRichard Henderson {
796951c6300SRichard Henderson     tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
797951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
798951c6300SRichard Henderson }
799951c6300SRichard Henderson 
800951c6300SRichard Henderson void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
801951c6300SRichard Henderson {
802951c6300SRichard Henderson     tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
803951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), 31);
804951c6300SRichard Henderson }
805951c6300SRichard Henderson 
806951c6300SRichard Henderson void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
807951c6300SRichard Henderson {
808951c6300SRichard Henderson     tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
809951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
810951c6300SRichard Henderson }
811951c6300SRichard Henderson 
812951c6300SRichard Henderson void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
813951c6300SRichard Henderson {
814951c6300SRichard Henderson     tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
815951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
816951c6300SRichard Henderson }
817951c6300SRichard Henderson 
818951c6300SRichard Henderson void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
819951c6300SRichard Henderson {
820951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
821951c6300SRichard Henderson     tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
822951c6300SRichard Henderson }
823951c6300SRichard Henderson 
824951c6300SRichard Henderson void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
825951c6300SRichard Henderson {
826951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
827951c6300SRichard Henderson     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
828951c6300SRichard Henderson }
829951c6300SRichard Henderson 
830951c6300SRichard Henderson void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
831951c6300SRichard Henderson {
832951c6300SRichard Henderson     /* Since arg2 and ret have different types,
833951c6300SRichard Henderson        they cannot be the same temporary */
834cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
835951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
836951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
837951c6300SRichard Henderson #else
838951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
839951c6300SRichard Henderson     tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
840951c6300SRichard Henderson #endif
841951c6300SRichard Henderson }
842951c6300SRichard Henderson 
843951c6300SRichard Henderson void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
844951c6300SRichard Henderson {
845cf811fffSPeter Maydell #ifdef HOST_WORDS_BIGENDIAN
846951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
847951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
848951c6300SRichard Henderson #else
849951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
850951c6300SRichard Henderson     tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
851951c6300SRichard Henderson #endif
852951c6300SRichard Henderson }
853951c6300SRichard Henderson 
854951c6300SRichard Henderson void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
855951c6300SRichard Henderson {
856951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
857951c6300SRichard Henderson     tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
858951c6300SRichard Henderson }
859951c6300SRichard Henderson 
860951c6300SRichard Henderson void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
861951c6300SRichard Henderson {
862951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
863951c6300SRichard Henderson     tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
864951c6300SRichard Henderson }
865951c6300SRichard Henderson 
866951c6300SRichard Henderson void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
867951c6300SRichard Henderson {
868951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
869951c6300SRichard Henderson     tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
870951c6300SRichard Henderson }
871951c6300SRichard Henderson 
872951c6300SRichard Henderson void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
873951c6300SRichard Henderson {
874951c6300SRichard Henderson     gen_helper_shl_i64(ret, arg1, arg2);
875951c6300SRichard Henderson }
876951c6300SRichard Henderson 
877951c6300SRichard Henderson void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
878951c6300SRichard Henderson {
879951c6300SRichard Henderson     gen_helper_shr_i64(ret, arg1, arg2);
880951c6300SRichard Henderson }
881951c6300SRichard Henderson 
882951c6300SRichard Henderson void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
883951c6300SRichard Henderson {
884951c6300SRichard Henderson     gen_helper_sar_i64(ret, arg1, arg2);
885951c6300SRichard Henderson }
886951c6300SRichard Henderson 
887951c6300SRichard Henderson void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
888951c6300SRichard Henderson {
889951c6300SRichard Henderson     TCGv_i64 t0;
890951c6300SRichard Henderson     TCGv_i32 t1;
891951c6300SRichard Henderson 
892951c6300SRichard Henderson     t0 = tcg_temp_new_i64();
893951c6300SRichard Henderson     t1 = tcg_temp_new_i32();
894951c6300SRichard Henderson 
895951c6300SRichard Henderson     tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
896951c6300SRichard Henderson                       TCGV_LOW(arg1), TCGV_LOW(arg2));
897951c6300SRichard Henderson 
898951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
899951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
900951c6300SRichard Henderson     tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
901951c6300SRichard Henderson     tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
902951c6300SRichard Henderson 
903951c6300SRichard Henderson     tcg_gen_mov_i64(ret, t0);
904951c6300SRichard Henderson     tcg_temp_free_i64(t0);
905951c6300SRichard Henderson     tcg_temp_free_i32(t1);
906951c6300SRichard Henderson }
907951c6300SRichard Henderson #endif /* TCG_TARGET_REG_SIZE == 32 */
908951c6300SRichard Henderson 
909951c6300SRichard Henderson void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
910951c6300SRichard Henderson {
911951c6300SRichard Henderson     /* some cases can be optimized here */
912951c6300SRichard Henderson     if (arg2 == 0) {
913951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
914951c6300SRichard Henderson     } else {
915951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
916951c6300SRichard Henderson         tcg_gen_add_i64(ret, arg1, t0);
917951c6300SRichard Henderson         tcg_temp_free_i64(t0);
918951c6300SRichard Henderson     }
919951c6300SRichard Henderson }
920951c6300SRichard Henderson 
921951c6300SRichard Henderson void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
922951c6300SRichard Henderson {
923951c6300SRichard Henderson     if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
924951c6300SRichard Henderson         /* Don't recurse with tcg_gen_neg_i64.  */
925951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
926951c6300SRichard Henderson     } else {
927951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg1);
928951c6300SRichard Henderson         tcg_gen_sub_i64(ret, t0, arg2);
929951c6300SRichard Henderson         tcg_temp_free_i64(t0);
930951c6300SRichard Henderson     }
931951c6300SRichard Henderson }
932951c6300SRichard Henderson 
933951c6300SRichard Henderson void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
934951c6300SRichard Henderson {
935951c6300SRichard Henderson     /* some cases can be optimized here */
936951c6300SRichard Henderson     if (arg2 == 0) {
937951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
938951c6300SRichard Henderson     } else {
939951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
940951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
941951c6300SRichard Henderson         tcg_temp_free_i64(t0);
942951c6300SRichard Henderson     }
943951c6300SRichard Henderson }
944951c6300SRichard Henderson 
945951c6300SRichard Henderson void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
946951c6300SRichard Henderson {
9473a13c3f3SRichard Henderson     TCGv_i64 t0;
9483a13c3f3SRichard Henderson 
9493a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
950951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
951951c6300SRichard Henderson         tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
9523a13c3f3SRichard Henderson         return;
9533a13c3f3SRichard Henderson     }
9543a13c3f3SRichard Henderson 
955951c6300SRichard Henderson     /* Some cases can be optimized here.  */
956951c6300SRichard Henderson     switch (arg2) {
957951c6300SRichard Henderson     case 0:
958951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
959951c6300SRichard Henderson         return;
960951c6300SRichard Henderson     case 0xffffffffffffffffull:
961951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
962951c6300SRichard Henderson         return;
963951c6300SRichard Henderson     case 0xffull:
964951c6300SRichard Henderson         /* Don't recurse with tcg_gen_ext8u_i64.  */
965951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext8u_i64) {
966951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
967951c6300SRichard Henderson             return;
968951c6300SRichard Henderson         }
969951c6300SRichard Henderson         break;
970951c6300SRichard Henderson     case 0xffffu:
971951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext16u_i64) {
972951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
973951c6300SRichard Henderson             return;
974951c6300SRichard Henderson         }
975951c6300SRichard Henderson         break;
976951c6300SRichard Henderson     case 0xffffffffull:
977951c6300SRichard Henderson         if (TCG_TARGET_HAS_ext32u_i64) {
978951c6300SRichard Henderson             tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
979951c6300SRichard Henderson             return;
980951c6300SRichard Henderson         }
981951c6300SRichard Henderson         break;
982951c6300SRichard Henderson     }
983951c6300SRichard Henderson     t0 = tcg_const_i64(arg2);
984951c6300SRichard Henderson     tcg_gen_and_i64(ret, arg1, t0);
985951c6300SRichard Henderson     tcg_temp_free_i64(t0);
986951c6300SRichard Henderson }
987951c6300SRichard Henderson 
988951c6300SRichard Henderson void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
989951c6300SRichard Henderson {
9903a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
991951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
992951c6300SRichard Henderson         tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
9933a13c3f3SRichard Henderson         return;
9943a13c3f3SRichard Henderson     }
995951c6300SRichard Henderson     /* Some cases can be optimized here.  */
996951c6300SRichard Henderson     if (arg2 == -1) {
997951c6300SRichard Henderson         tcg_gen_movi_i64(ret, -1);
998951c6300SRichard Henderson     } else if (arg2 == 0) {
999951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1000951c6300SRichard Henderson     } else {
1001951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1002951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1003951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1004951c6300SRichard Henderson     }
1005951c6300SRichard Henderson }
1006951c6300SRichard Henderson 
1007951c6300SRichard Henderson void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1008951c6300SRichard Henderson {
10093a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1010951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1011951c6300SRichard Henderson         tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
10123a13c3f3SRichard Henderson         return;
10133a13c3f3SRichard Henderson     }
1014951c6300SRichard Henderson     /* Some cases can be optimized here.  */
1015951c6300SRichard Henderson     if (arg2 == 0) {
1016951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1017951c6300SRichard Henderson     } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1018951c6300SRichard Henderson         /* Don't recurse with tcg_gen_not_i64.  */
1019951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1020951c6300SRichard Henderson     } else {
1021951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1022951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, t0);
1023951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1024951c6300SRichard Henderson     }
1025951c6300SRichard Henderson }
1026951c6300SRichard Henderson 
1027951c6300SRichard Henderson static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1028951c6300SRichard Henderson                                       unsigned c, bool right, bool arith)
1029951c6300SRichard Henderson {
1030951c6300SRichard Henderson     tcg_debug_assert(c < 64);
1031951c6300SRichard Henderson     if (c == 0) {
1032951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1033951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1034951c6300SRichard Henderson     } else if (c >= 32) {
1035951c6300SRichard Henderson         c -= 32;
1036951c6300SRichard Henderson         if (right) {
1037951c6300SRichard Henderson             if (arith) {
1038951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1039951c6300SRichard Henderson                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1040951c6300SRichard Henderson             } else {
1041951c6300SRichard Henderson                 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1042951c6300SRichard Henderson                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1043951c6300SRichard Henderson             }
1044951c6300SRichard Henderson         } else {
1045951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1046951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1047951c6300SRichard Henderson         }
1048951c6300SRichard Henderson     } else {
1049951c6300SRichard Henderson         TCGv_i32 t0, t1;
1050951c6300SRichard Henderson 
1051951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1052951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1053951c6300SRichard Henderson         if (right) {
1054951c6300SRichard Henderson             tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
1055951c6300SRichard Henderson             if (arith) {
1056951c6300SRichard Henderson                 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
1057951c6300SRichard Henderson             } else {
1058951c6300SRichard Henderson                 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
1059951c6300SRichard Henderson             }
1060951c6300SRichard Henderson             tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1061951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
1062951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
1063951c6300SRichard Henderson         } else {
1064951c6300SRichard Henderson             tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
1065951c6300SRichard Henderson             /* Note: ret can be the same as arg1, so we use t1 */
1066951c6300SRichard Henderson             tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
1067951c6300SRichard Henderson             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1068951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
1069951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1070951c6300SRichard Henderson         }
1071951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1072951c6300SRichard Henderson         tcg_temp_free_i32(t1);
1073951c6300SRichard Henderson     }
1074951c6300SRichard Henderson }
1075951c6300SRichard Henderson 
1076951c6300SRichard Henderson void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1077951c6300SRichard Henderson {
1078951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
10793a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
10803a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
10813a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1082951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1083951c6300SRichard Henderson     } else {
1084951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1085951c6300SRichard Henderson         tcg_gen_shl_i64(ret, arg1, t0);
1086951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1087951c6300SRichard Henderson     }
1088951c6300SRichard Henderson }
1089951c6300SRichard Henderson 
1090951c6300SRichard Henderson void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1091951c6300SRichard Henderson {
1092951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
10933a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
10943a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
10953a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1096951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1097951c6300SRichard Henderson     } else {
1098951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1099951c6300SRichard Henderson         tcg_gen_shr_i64(ret, arg1, t0);
1100951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1101951c6300SRichard Henderson     }
1102951c6300SRichard Henderson }
1103951c6300SRichard Henderson 
1104951c6300SRichard Henderson void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1105951c6300SRichard Henderson {
1106951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
11073a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
11083a13c3f3SRichard Henderson         tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
11093a13c3f3SRichard Henderson     } else if (arg2 == 0) {
1110951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1111951c6300SRichard Henderson     } else {
1112951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1113951c6300SRichard Henderson         tcg_gen_sar_i64(ret, arg1, t0);
1114951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1115951c6300SRichard Henderson     }
1116951c6300SRichard Henderson }
1117951c6300SRichard Henderson 
111842a268c2SRichard Henderson void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1119951c6300SRichard Henderson {
1120951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
112142a268c2SRichard Henderson         tcg_gen_br(l);
1122951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
11233a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1124951c6300SRichard Henderson             tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1125951c6300SRichard Henderson                               TCGV_HIGH(arg1), TCGV_LOW(arg2),
112642a268c2SRichard Henderson                               TCGV_HIGH(arg2), cond, label_arg(l));
11273a13c3f3SRichard Henderson         } else {
112842a268c2SRichard Henderson             tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
112942a268c2SRichard Henderson                               label_arg(l));
11303a13c3f3SRichard Henderson         }
1131951c6300SRichard Henderson     }
1132951c6300SRichard Henderson }
1133951c6300SRichard Henderson 
113442a268c2SRichard Henderson void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1135951c6300SRichard Henderson {
1136951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
113742a268c2SRichard Henderson         tcg_gen_br(l);
1138951c6300SRichard Henderson     } else if (cond != TCG_COND_NEVER) {
1139951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
114042a268c2SRichard Henderson         tcg_gen_brcond_i64(cond, arg1, t0, l);
1141951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1142951c6300SRichard Henderson     }
1143951c6300SRichard Henderson }
1144951c6300SRichard Henderson 
1145951c6300SRichard Henderson void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1146951c6300SRichard Henderson                          TCGv_i64 arg1, TCGv_i64 arg2)
1147951c6300SRichard Henderson {
1148951c6300SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
1149951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 1);
1150951c6300SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
1151951c6300SRichard Henderson         tcg_gen_movi_i64(ret, 0);
1152951c6300SRichard Henderson     } else {
11533a13c3f3SRichard Henderson         if (TCG_TARGET_REG_BITS == 32) {
1154951c6300SRichard Henderson             tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1155951c6300SRichard Henderson                              TCGV_LOW(arg1), TCGV_HIGH(arg1),
1156951c6300SRichard Henderson                              TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1157951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
11583a13c3f3SRichard Henderson         } else {
1159951c6300SRichard Henderson             tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
11603a13c3f3SRichard Henderson         }
1161951c6300SRichard Henderson     }
1162951c6300SRichard Henderson }
1163951c6300SRichard Henderson 
1164951c6300SRichard Henderson void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1165951c6300SRichard Henderson                           TCGv_i64 arg1, int64_t arg2)
1166951c6300SRichard Henderson {
1167951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1168951c6300SRichard Henderson     tcg_gen_setcond_i64(cond, ret, arg1, t0);
1169951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1170951c6300SRichard Henderson }
1171951c6300SRichard Henderson 
1172951c6300SRichard Henderson void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1173951c6300SRichard Henderson {
1174951c6300SRichard Henderson     TCGv_i64 t0 = tcg_const_i64(arg2);
1175951c6300SRichard Henderson     tcg_gen_mul_i64(ret, arg1, t0);
1176951c6300SRichard Henderson     tcg_temp_free_i64(t0);
1177951c6300SRichard Henderson }
1178951c6300SRichard Henderson 
1179951c6300SRichard Henderson void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1180951c6300SRichard Henderson {
1181951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1182951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1183951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1184951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1185951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1186951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1187951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1188951c6300SRichard Henderson     } else {
1189951c6300SRichard Henderson         gen_helper_div_i64(ret, arg1, arg2);
1190951c6300SRichard Henderson     }
1191951c6300SRichard Henderson }
1192951c6300SRichard Henderson 
1193951c6300SRichard Henderson void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1194951c6300SRichard Henderson {
1195951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1196951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1197951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1198951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1199951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1200951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1201951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1202951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1203951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1204951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1205951c6300SRichard Henderson         tcg_gen_sari_i64(t0, arg1, 63);
1206951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1207951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1208951c6300SRichard Henderson     } else {
1209951c6300SRichard Henderson         gen_helper_rem_i64(ret, arg1, arg2);
1210951c6300SRichard Henderson     }
1211951c6300SRichard Henderson }
1212951c6300SRichard Henderson 
1213951c6300SRichard Henderson void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1214951c6300SRichard Henderson {
1215951c6300SRichard Henderson     if (TCG_TARGET_HAS_div_i64) {
1216951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1217951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1218951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1219951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1220951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1221951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1222951c6300SRichard Henderson     } else {
1223951c6300SRichard Henderson         gen_helper_divu_i64(ret, arg1, arg2);
1224951c6300SRichard Henderson     }
1225951c6300SRichard Henderson }
1226951c6300SRichard Henderson 
1227951c6300SRichard Henderson void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1228951c6300SRichard Henderson {
1229951c6300SRichard Henderson     if (TCG_TARGET_HAS_rem_i64) {
1230951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1231951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div_i64) {
1232951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1233951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1234951c6300SRichard Henderson         tcg_gen_mul_i64(t0, t0, arg2);
1235951c6300SRichard Henderson         tcg_gen_sub_i64(ret, arg1, t0);
1236951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1237951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_div2_i64) {
1238951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1239951c6300SRichard Henderson         tcg_gen_movi_i64(t0, 0);
1240951c6300SRichard Henderson         tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1241951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1242951c6300SRichard Henderson     } else {
1243951c6300SRichard Henderson         gen_helper_remu_i64(ret, arg1, arg2);
1244951c6300SRichard Henderson     }
1245951c6300SRichard Henderson }
1246951c6300SRichard Henderson 
1247951c6300SRichard Henderson void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1248951c6300SRichard Henderson {
12493a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1250951c6300SRichard Henderson         tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1251951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
12523a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8s_i64) {
1253951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1254951c6300SRichard Henderson     } else {
1255951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 56);
1256951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 56);
1257951c6300SRichard Henderson     }
1258951c6300SRichard Henderson }
1259951c6300SRichard Henderson 
1260951c6300SRichard Henderson void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1261951c6300SRichard Henderson {
12623a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1263951c6300SRichard Henderson         tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1264951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
12653a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16s_i64) {
1266951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1267951c6300SRichard Henderson     } else {
1268951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 48);
1269951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 48);
1270951c6300SRichard Henderson     }
1271951c6300SRichard Henderson }
1272951c6300SRichard Henderson 
1273951c6300SRichard Henderson void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1274951c6300SRichard Henderson {
12753a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1276951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1277951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
12783a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32s_i64) {
1279951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1280951c6300SRichard Henderson     } else {
1281951c6300SRichard Henderson         tcg_gen_shli_i64(ret, arg, 32);
1282951c6300SRichard Henderson         tcg_gen_sari_i64(ret, ret, 32);
1283951c6300SRichard Henderson     }
1284951c6300SRichard Henderson }
1285951c6300SRichard Henderson 
1286951c6300SRichard Henderson void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1287951c6300SRichard Henderson {
12883a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1289951c6300SRichard Henderson         tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1290951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
12913a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext8u_i64) {
1292951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1293951c6300SRichard Henderson     } else {
1294951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffu);
1295951c6300SRichard Henderson     }
1296951c6300SRichard Henderson }
1297951c6300SRichard Henderson 
1298951c6300SRichard Henderson void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1299951c6300SRichard Henderson {
13003a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1301951c6300SRichard Henderson         tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1302951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
13033a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext16u_i64) {
1304951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1305951c6300SRichard Henderson     } else {
1306951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffu);
1307951c6300SRichard Henderson     }
1308951c6300SRichard Henderson }
1309951c6300SRichard Henderson 
1310951c6300SRichard Henderson void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1311951c6300SRichard Henderson {
13123a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1313951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1314951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
13153a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_ext32u_i64) {
1316951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1317951c6300SRichard Henderson     } else {
1318951c6300SRichard Henderson         tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1319951c6300SRichard Henderson     }
1320951c6300SRichard Henderson }
1321951c6300SRichard Henderson 
1322951c6300SRichard Henderson /* Note: we assume the six high bytes are set to zero */
1323951c6300SRichard Henderson void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
1324951c6300SRichard Henderson {
13253a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1326951c6300SRichard Henderson         tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1327951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
13283a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap16_i64) {
1329951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
1330951c6300SRichard Henderson     } else {
1331951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1332951c6300SRichard Henderson 
1333951c6300SRichard Henderson         tcg_gen_ext8u_i64(t0, arg);
1334951c6300SRichard Henderson         tcg_gen_shli_i64(t0, t0, 8);
1335951c6300SRichard Henderson         tcg_gen_shri_i64(ret, arg, 8);
1336951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t0);
1337951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1338951c6300SRichard Henderson     }
1339951c6300SRichard Henderson }
1340951c6300SRichard Henderson 
1341951c6300SRichard Henderson /* Note: we assume the four high bytes are set to zero */
1342951c6300SRichard Henderson void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
1343951c6300SRichard Henderson {
13443a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1345951c6300SRichard Henderson         tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1346951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
13473a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap32_i64) {
1348951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
1349951c6300SRichard Henderson     } else {
1350951c6300SRichard Henderson         TCGv_i64 t0, t1;
1351951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1352951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1353951c6300SRichard Henderson 
1354951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 24);
1355951c6300SRichard Henderson         tcg_gen_ext32u_i64(t0, t0);
1356951c6300SRichard Henderson 
1357951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1358951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1359951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1360951c6300SRichard Henderson 
1361951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1362951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1363951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1364951c6300SRichard Henderson 
1365951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1366951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1367951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1368951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1369951c6300SRichard Henderson     }
1370951c6300SRichard Henderson }
1371951c6300SRichard Henderson 
1372951c6300SRichard Henderson void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1373951c6300SRichard Henderson {
13743a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1375951c6300SRichard Henderson         TCGv_i32 t0, t1;
1376951c6300SRichard Henderson         t0 = tcg_temp_new_i32();
1377951c6300SRichard Henderson         t1 = tcg_temp_new_i32();
1378951c6300SRichard Henderson 
1379951c6300SRichard Henderson         tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1380951c6300SRichard Henderson         tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1381951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1382951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1383951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1384951c6300SRichard Henderson         tcg_temp_free_i32(t1);
13853a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_bswap64_i64) {
1386951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
1387951c6300SRichard Henderson     } else {
1388951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1389951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1390951c6300SRichard Henderson 
1391951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg, 56);
1392951c6300SRichard Henderson 
1393951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1394951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 40);
1395951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1396951c6300SRichard Henderson 
1397951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0x00ff0000);
1398951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 24);
1399951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1400951c6300SRichard Henderson 
1401951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg, 0xff000000);
1402951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, 8);
1403951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1404951c6300SRichard Henderson 
1405951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 8);
1406951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0xff000000);
1407951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1408951c6300SRichard Henderson 
1409951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 24);
1410951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x00ff0000);
1411951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1412951c6300SRichard Henderson 
1413951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 40);
1414951c6300SRichard Henderson         tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1415951c6300SRichard Henderson         tcg_gen_or_i64(t0, t0, t1);
1416951c6300SRichard Henderson 
1417951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg, 56);
1418951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1419951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1420951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1421951c6300SRichard Henderson     }
1422951c6300SRichard Henderson }
1423951c6300SRichard Henderson 
1424951c6300SRichard Henderson void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1425951c6300SRichard Henderson {
14263a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14273a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
14283a13c3f3SRichard Henderson         tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
14293a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_not_i64) {
1430951c6300SRichard Henderson         tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1431951c6300SRichard Henderson     } else {
1432951c6300SRichard Henderson         tcg_gen_xori_i64(ret, arg, -1);
1433951c6300SRichard Henderson     }
1434951c6300SRichard Henderson }
1435951c6300SRichard Henderson 
1436951c6300SRichard Henderson void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1437951c6300SRichard Henderson {
14383a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14393a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
14403a13c3f3SRichard Henderson         tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
14413a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_andc_i64) {
1442951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1443951c6300SRichard Henderson     } else {
1444951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1445951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1446951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, t0);
1447951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1448951c6300SRichard Henderson     }
1449951c6300SRichard Henderson }
1450951c6300SRichard Henderson 
1451951c6300SRichard Henderson void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1452951c6300SRichard Henderson {
14533a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14543a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
14553a13c3f3SRichard Henderson         tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
14563a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_eqv_i64) {
1457951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1458951c6300SRichard Henderson     } else {
1459951c6300SRichard Henderson         tcg_gen_xor_i64(ret, arg1, arg2);
1460951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1461951c6300SRichard Henderson     }
1462951c6300SRichard Henderson }
1463951c6300SRichard Henderson 
1464951c6300SRichard Henderson void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1465951c6300SRichard Henderson {
14663a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14673a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
14683a13c3f3SRichard Henderson         tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
14693a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nand_i64) {
1470951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1471951c6300SRichard Henderson     } else {
1472951c6300SRichard Henderson         tcg_gen_and_i64(ret, arg1, arg2);
1473951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1474951c6300SRichard Henderson     }
1475951c6300SRichard Henderson }
1476951c6300SRichard Henderson 
1477951c6300SRichard Henderson void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1478951c6300SRichard Henderson {
14793a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14803a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
14813a13c3f3SRichard Henderson         tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
14823a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_nor_i64) {
1483951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1484951c6300SRichard Henderson     } else {
1485951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, arg2);
1486951c6300SRichard Henderson         tcg_gen_not_i64(ret, ret);
1487951c6300SRichard Henderson     }
1488951c6300SRichard Henderson }
1489951c6300SRichard Henderson 
1490951c6300SRichard Henderson void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1491951c6300SRichard Henderson {
14923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
14933a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
14943a13c3f3SRichard Henderson         tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
14953a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_orc_i64) {
1496951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1497951c6300SRichard Henderson     } else {
1498951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1499951c6300SRichard Henderson         tcg_gen_not_i64(t0, arg2);
1500951c6300SRichard Henderson         tcg_gen_or_i64(ret, arg1, t0);
1501951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1502951c6300SRichard Henderson     }
1503951c6300SRichard Henderson }
1504951c6300SRichard Henderson 
1505951c6300SRichard Henderson void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1506951c6300SRichard Henderson {
1507951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1508951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1509951c6300SRichard Henderson     } else {
1510951c6300SRichard Henderson         TCGv_i64 t0, t1;
1511951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1512951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1513951c6300SRichard Henderson         tcg_gen_shl_i64(t0, arg1, arg2);
1514951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1515951c6300SRichard Henderson         tcg_gen_shr_i64(t1, arg1, t1);
1516951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1517951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1518951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1519951c6300SRichard Henderson     }
1520951c6300SRichard Henderson }
1521951c6300SRichard Henderson 
1522951c6300SRichard Henderson void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1523951c6300SRichard Henderson {
1524951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1525951c6300SRichard Henderson     /* some cases can be optimized here */
1526951c6300SRichard Henderson     if (arg2 == 0) {
1527951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1528951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_rot_i64) {
1529951c6300SRichard Henderson         TCGv_i64 t0 = tcg_const_i64(arg2);
1530951c6300SRichard Henderson         tcg_gen_rotl_i64(ret, arg1, t0);
1531951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1532951c6300SRichard Henderson     } else {
1533951c6300SRichard Henderson         TCGv_i64 t0, t1;
1534951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1535951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1536951c6300SRichard Henderson         tcg_gen_shli_i64(t0, arg1, arg2);
1537951c6300SRichard Henderson         tcg_gen_shri_i64(t1, arg1, 64 - arg2);
1538951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1539951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1540951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1541951c6300SRichard Henderson     }
1542951c6300SRichard Henderson }
1543951c6300SRichard Henderson 
1544951c6300SRichard Henderson void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1545951c6300SRichard Henderson {
1546951c6300SRichard Henderson     if (TCG_TARGET_HAS_rot_i64) {
1547951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
1548951c6300SRichard Henderson     } else {
1549951c6300SRichard Henderson         TCGv_i64 t0, t1;
1550951c6300SRichard Henderson         t0 = tcg_temp_new_i64();
1551951c6300SRichard Henderson         t1 = tcg_temp_new_i64();
1552951c6300SRichard Henderson         tcg_gen_shr_i64(t0, arg1, arg2);
1553951c6300SRichard Henderson         tcg_gen_subfi_i64(t1, 64, arg2);
1554951c6300SRichard Henderson         tcg_gen_shl_i64(t1, arg1, t1);
1555951c6300SRichard Henderson         tcg_gen_or_i64(ret, t0, t1);
1556951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1557951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1558951c6300SRichard Henderson     }
1559951c6300SRichard Henderson }
1560951c6300SRichard Henderson 
1561951c6300SRichard Henderson void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1562951c6300SRichard Henderson {
1563951c6300SRichard Henderson     tcg_debug_assert(arg2 < 64);
1564951c6300SRichard Henderson     /* some cases can be optimized here */
1565951c6300SRichard Henderson     if (arg2 == 0) {
1566951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg1);
1567951c6300SRichard Henderson     } else {
1568951c6300SRichard Henderson         tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
1569951c6300SRichard Henderson     }
1570951c6300SRichard Henderson }
1571951c6300SRichard Henderson 
1572951c6300SRichard Henderson void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
1573951c6300SRichard Henderson                          unsigned int ofs, unsigned int len)
1574951c6300SRichard Henderson {
1575951c6300SRichard Henderson     uint64_t mask;
1576951c6300SRichard Henderson     TCGv_i64 t1;
1577951c6300SRichard Henderson 
1578951c6300SRichard Henderson     tcg_debug_assert(ofs < 64);
1579951c6300SRichard Henderson     tcg_debug_assert(len <= 64);
1580951c6300SRichard Henderson     tcg_debug_assert(ofs + len <= 64);
1581951c6300SRichard Henderson 
1582951c6300SRichard Henderson     if (ofs == 0 && len == 64) {
1583951c6300SRichard Henderson         tcg_gen_mov_i64(ret, arg2);
1584951c6300SRichard Henderson         return;
1585951c6300SRichard Henderson     }
1586951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
1587951c6300SRichard Henderson         tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
1588951c6300SRichard Henderson         return;
1589951c6300SRichard Henderson     }
1590951c6300SRichard Henderson 
15913a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1592951c6300SRichard Henderson         if (ofs >= 32) {
1593951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
1594951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs - 32, len);
1595951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1596951c6300SRichard Henderson             return;
1597951c6300SRichard Henderson         }
1598951c6300SRichard Henderson         if (ofs + len <= 32) {
1599951c6300SRichard Henderson             tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
1600951c6300SRichard Henderson                                 TCGV_LOW(arg2), ofs, len);
1601951c6300SRichard Henderson             tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1602951c6300SRichard Henderson             return;
1603951c6300SRichard Henderson         }
16043a13c3f3SRichard Henderson     }
1605951c6300SRichard Henderson 
1606951c6300SRichard Henderson     mask = (1ull << len) - 1;
1607951c6300SRichard Henderson     t1 = tcg_temp_new_i64();
1608951c6300SRichard Henderson 
1609951c6300SRichard Henderson     if (ofs + len < 64) {
1610951c6300SRichard Henderson         tcg_gen_andi_i64(t1, arg2, mask);
1611951c6300SRichard Henderson         tcg_gen_shli_i64(t1, t1, ofs);
1612951c6300SRichard Henderson     } else {
1613951c6300SRichard Henderson         tcg_gen_shli_i64(t1, arg2, ofs);
1614951c6300SRichard Henderson     }
1615951c6300SRichard Henderson     tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
1616951c6300SRichard Henderson     tcg_gen_or_i64(ret, ret, t1);
1617951c6300SRichard Henderson 
1618951c6300SRichard Henderson     tcg_temp_free_i64(t1);
1619951c6300SRichard Henderson }
1620951c6300SRichard Henderson 
1621951c6300SRichard Henderson void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
1622951c6300SRichard Henderson                          TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
1623951c6300SRichard Henderson {
162437ed3bf1SRichard Henderson     if (cond == TCG_COND_ALWAYS) {
162537ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v1);
162637ed3bf1SRichard Henderson     } else if (cond == TCG_COND_NEVER) {
162737ed3bf1SRichard Henderson         tcg_gen_mov_i64(ret, v2);
162837ed3bf1SRichard Henderson     } else if (TCG_TARGET_REG_BITS == 32) {
1629951c6300SRichard Henderson         TCGv_i32 t0 = tcg_temp_new_i32();
1630951c6300SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
1631951c6300SRichard Henderson         tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
1632951c6300SRichard Henderson                          TCGV_LOW(c1), TCGV_HIGH(c1),
1633951c6300SRichard Henderson                          TCGV_LOW(c2), TCGV_HIGH(c2), cond);
1634951c6300SRichard Henderson 
1635951c6300SRichard Henderson         if (TCG_TARGET_HAS_movcond_i32) {
1636951c6300SRichard Henderson             tcg_gen_movi_i32(t1, 0);
1637951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
1638951c6300SRichard Henderson                                 TCGV_LOW(v1), TCGV_LOW(v2));
1639951c6300SRichard Henderson             tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
1640951c6300SRichard Henderson                                 TCGV_HIGH(v1), TCGV_HIGH(v2));
1641951c6300SRichard Henderson         } else {
1642951c6300SRichard Henderson             tcg_gen_neg_i32(t0, t0);
1643951c6300SRichard Henderson 
1644951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
1645951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
1646951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
1647951c6300SRichard Henderson 
1648951c6300SRichard Henderson             tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
1649951c6300SRichard Henderson             tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
1650951c6300SRichard Henderson             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
1651951c6300SRichard Henderson         }
1652951c6300SRichard Henderson         tcg_temp_free_i32(t0);
1653951c6300SRichard Henderson         tcg_temp_free_i32(t1);
16543a13c3f3SRichard Henderson     } else if (TCG_TARGET_HAS_movcond_i64) {
1655951c6300SRichard Henderson         tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
1656951c6300SRichard Henderson     } else {
1657951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1658951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1659951c6300SRichard Henderson         tcg_gen_setcond_i64(cond, t0, c1, c2);
1660951c6300SRichard Henderson         tcg_gen_neg_i64(t0, t0);
1661951c6300SRichard Henderson         tcg_gen_and_i64(t1, v1, t0);
1662951c6300SRichard Henderson         tcg_gen_andc_i64(ret, v2, t0);
1663951c6300SRichard Henderson         tcg_gen_or_i64(ret, ret, t1);
1664951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1665951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1666951c6300SRichard Henderson     }
1667951c6300SRichard Henderson }
1668951c6300SRichard Henderson 
1669951c6300SRichard Henderson void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
1670951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
1671951c6300SRichard Henderson {
1672951c6300SRichard Henderson     if (TCG_TARGET_HAS_add2_i64) {
1673951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
1674951c6300SRichard Henderson     } else {
1675951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1676951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1677951c6300SRichard Henderson         tcg_gen_add_i64(t0, al, bl);
1678951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
1679951c6300SRichard Henderson         tcg_gen_add_i64(rh, ah, bh);
1680951c6300SRichard Henderson         tcg_gen_add_i64(rh, rh, t1);
1681951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
1682951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1683951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1684951c6300SRichard Henderson     }
1685951c6300SRichard Henderson }
1686951c6300SRichard Henderson 
1687951c6300SRichard Henderson void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
1688951c6300SRichard Henderson                       TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
1689951c6300SRichard Henderson {
1690951c6300SRichard Henderson     if (TCG_TARGET_HAS_sub2_i64) {
1691951c6300SRichard Henderson         tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
1692951c6300SRichard Henderson     } else {
1693951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1694951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1695951c6300SRichard Henderson         tcg_gen_sub_i64(t0, al, bl);
1696951c6300SRichard Henderson         tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
1697951c6300SRichard Henderson         tcg_gen_sub_i64(rh, ah, bh);
1698951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t1);
1699951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
1700951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1701951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1702951c6300SRichard Henderson     }
1703951c6300SRichard Henderson }
1704951c6300SRichard Henderson 
1705951c6300SRichard Henderson void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
1706951c6300SRichard Henderson {
1707951c6300SRichard Henderson     if (TCG_TARGET_HAS_mulu2_i64) {
1708951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
1709951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_muluh_i64) {
1710951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1711951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
1712951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
1713951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
1714951c6300SRichard Henderson         tcg_temp_free_i64(t);
1715951c6300SRichard Henderson     } else {
1716951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1717951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
1718951c6300SRichard Henderson         gen_helper_muluh_i64(rh, arg1, arg2);
1719951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
1720951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1721951c6300SRichard Henderson     }
1722951c6300SRichard Henderson }
1723951c6300SRichard Henderson 
1724951c6300SRichard Henderson void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
1725951c6300SRichard Henderson {
1726951c6300SRichard Henderson     if (TCG_TARGET_HAS_muls2_i64) {
1727951c6300SRichard Henderson         tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
1728951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulsh_i64) {
1729951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1730951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
1731951c6300SRichard Henderson         tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
1732951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t);
1733951c6300SRichard Henderson         tcg_temp_free_i64(t);
1734951c6300SRichard Henderson     } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
1735951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1736951c6300SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
1737951c6300SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
1738951c6300SRichard Henderson         TCGv_i64 t3 = tcg_temp_new_i64();
1739951c6300SRichard Henderson         tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
1740951c6300SRichard Henderson         /* Adjust for negative inputs.  */
1741951c6300SRichard Henderson         tcg_gen_sari_i64(t2, arg1, 63);
1742951c6300SRichard Henderson         tcg_gen_sari_i64(t3, arg2, 63);
1743951c6300SRichard Henderson         tcg_gen_and_i64(t2, t2, arg2);
1744951c6300SRichard Henderson         tcg_gen_and_i64(t3, t3, arg1);
1745951c6300SRichard Henderson         tcg_gen_sub_i64(rh, t1, t2);
1746951c6300SRichard Henderson         tcg_gen_sub_i64(rh, rh, t3);
1747951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
1748951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1749951c6300SRichard Henderson         tcg_temp_free_i64(t1);
1750951c6300SRichard Henderson         tcg_temp_free_i64(t2);
1751951c6300SRichard Henderson         tcg_temp_free_i64(t3);
1752951c6300SRichard Henderson     } else {
1753951c6300SRichard Henderson         TCGv_i64 t0 = tcg_temp_new_i64();
1754951c6300SRichard Henderson         tcg_gen_mul_i64(t0, arg1, arg2);
1755951c6300SRichard Henderson         gen_helper_mulsh_i64(rh, arg1, arg2);
1756951c6300SRichard Henderson         tcg_gen_mov_i64(rl, t0);
1757951c6300SRichard Henderson         tcg_temp_free_i64(t0);
1758951c6300SRichard Henderson     }
1759951c6300SRichard Henderson }
1760951c6300SRichard Henderson 
1761951c6300SRichard Henderson /* Size changing operations.  */
1762951c6300SRichard Henderson 
1763609ad705SRichard Henderson void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
1764951c6300SRichard Henderson {
17653a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1766951c6300SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_LOW(arg));
1767609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrl_i64_i32) {
1768609ad705SRichard Henderson         tcg_gen_op2(&tcg_ctx, INDEX_op_extrl_i64_i32,
1769609ad705SRichard Henderson                     GET_TCGV_I32(ret), GET_TCGV_I64(arg));
1770951c6300SRichard Henderson     } else {
1771951c6300SRichard Henderson         tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
1772609ad705SRichard Henderson     }
1773609ad705SRichard Henderson }
1774609ad705SRichard Henderson 
1775609ad705SRichard Henderson void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
1776609ad705SRichard Henderson {
1777609ad705SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1778609ad705SRichard Henderson         tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
1779609ad705SRichard Henderson     } else if (TCG_TARGET_HAS_extrh_i64_i32) {
1780609ad705SRichard Henderson         tcg_gen_op2(&tcg_ctx, INDEX_op_extrh_i64_i32,
1781609ad705SRichard Henderson                     GET_TCGV_I32(ret), GET_TCGV_I64(arg));
1782951c6300SRichard Henderson     } else {
1783951c6300SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
1784609ad705SRichard Henderson         tcg_gen_shri_i64(t, arg, 32);
1785951c6300SRichard Henderson         tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(t)));
1786951c6300SRichard Henderson         tcg_temp_free_i64(t);
1787951c6300SRichard Henderson     }
1788951c6300SRichard Henderson }
1789951c6300SRichard Henderson 
1790951c6300SRichard Henderson void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
1791951c6300SRichard Henderson {
17923a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1793951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
1794951c6300SRichard Henderson         tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
17953a13c3f3SRichard Henderson     } else {
17964f2331e5SAurelien Jarno         tcg_gen_op2(&tcg_ctx, INDEX_op_extu_i32_i64,
17974f2331e5SAurelien Jarno                     GET_TCGV_I64(ret), GET_TCGV_I32(arg));
17983a13c3f3SRichard Henderson     }
1799951c6300SRichard Henderson }
1800951c6300SRichard Henderson 
1801951c6300SRichard Henderson void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
1802951c6300SRichard Henderson {
18033a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1804951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(ret), arg);
1805951c6300SRichard Henderson         tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
18063a13c3f3SRichard Henderson     } else {
18074f2331e5SAurelien Jarno         tcg_gen_op2(&tcg_ctx, INDEX_op_ext_i32_i64,
18084f2331e5SAurelien Jarno                     GET_TCGV_I64(ret), GET_TCGV_I32(arg));
18093a13c3f3SRichard Henderson     }
1810951c6300SRichard Henderson }
1811951c6300SRichard Henderson 
1812951c6300SRichard Henderson void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
1813951c6300SRichard Henderson {
18143a13c3f3SRichard Henderson     TCGv_i64 tmp;
18153a13c3f3SRichard Henderson 
18163a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1817951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_LOW(dest), low);
1818951c6300SRichard Henderson         tcg_gen_mov_i32(TCGV_HIGH(dest), high);
18193a13c3f3SRichard Henderson         return;
18203a13c3f3SRichard Henderson     }
18213a13c3f3SRichard Henderson 
18223a13c3f3SRichard Henderson     tmp = tcg_temp_new_i64();
1823951c6300SRichard Henderson     /* These extensions are only needed for type correctness.
1824951c6300SRichard Henderson        We may be able to do better given target specific information.  */
1825951c6300SRichard Henderson     tcg_gen_extu_i32_i64(tmp, high);
1826951c6300SRichard Henderson     tcg_gen_extu_i32_i64(dest, low);
1827951c6300SRichard Henderson     /* If deposit is available, use it.  Otherwise use the extra
1828951c6300SRichard Henderson        knowledge that we have of the zero-extensions above.  */
1829951c6300SRichard Henderson     if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
1830951c6300SRichard Henderson         tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
1831951c6300SRichard Henderson     } else {
1832951c6300SRichard Henderson         tcg_gen_shli_i64(tmp, tmp, 32);
1833951c6300SRichard Henderson         tcg_gen_or_i64(dest, dest, tmp);
1834951c6300SRichard Henderson     }
1835951c6300SRichard Henderson     tcg_temp_free_i64(tmp);
1836951c6300SRichard Henderson }
1837951c6300SRichard Henderson 
1838951c6300SRichard Henderson void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
1839951c6300SRichard Henderson {
18403a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
1841951c6300SRichard Henderson         tcg_gen_mov_i32(lo, TCGV_LOW(arg));
1842951c6300SRichard Henderson         tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
18433a13c3f3SRichard Henderson     } else {
1844609ad705SRichard Henderson         tcg_gen_extrl_i64_i32(lo, arg);
1845609ad705SRichard Henderson         tcg_gen_extrh_i64_i32(hi, arg);
18463a13c3f3SRichard Henderson     }
1847951c6300SRichard Henderson }
1848951c6300SRichard Henderson 
1849951c6300SRichard Henderson void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
1850951c6300SRichard Henderson {
1851951c6300SRichard Henderson     tcg_gen_ext32u_i64(lo, arg);
1852951c6300SRichard Henderson     tcg_gen_shri_i64(hi, arg, 32);
1853951c6300SRichard Henderson }
1854951c6300SRichard Henderson 
1855951c6300SRichard Henderson /* QEMU specific operations.  */
1856951c6300SRichard Henderson 
1857951c6300SRichard Henderson void tcg_gen_goto_tb(unsigned idx)
1858951c6300SRichard Henderson {
1859951c6300SRichard Henderson     /* We only support two chained exits.  */
1860951c6300SRichard Henderson     tcg_debug_assert(idx <= 1);
1861951c6300SRichard Henderson #ifdef CONFIG_DEBUG_TCG
1862951c6300SRichard Henderson     /* Verify that we havn't seen this numbered exit before.  */
1863951c6300SRichard Henderson     tcg_debug_assert((tcg_ctx.goto_tb_issue_mask & (1 << idx)) == 0);
1864951c6300SRichard Henderson     tcg_ctx.goto_tb_issue_mask |= 1 << idx;
1865951c6300SRichard Henderson #endif
1866951c6300SRichard Henderson     tcg_gen_op1i(INDEX_op_goto_tb, idx);
1867951c6300SRichard Henderson }
1868951c6300SRichard Henderson 
1869951c6300SRichard Henderson static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
1870951c6300SRichard Henderson {
18711f00b27fSSergey Sorokin     /* Trigger the asserts within as early as possible.  */
18721f00b27fSSergey Sorokin     (void)get_alignment_bits(op);
18731f00b27fSSergey Sorokin 
1874951c6300SRichard Henderson     switch (op & MO_SIZE) {
1875951c6300SRichard Henderson     case MO_8:
1876951c6300SRichard Henderson         op &= ~MO_BSWAP;
1877951c6300SRichard Henderson         break;
1878951c6300SRichard Henderson     case MO_16:
1879951c6300SRichard Henderson         break;
1880951c6300SRichard Henderson     case MO_32:
1881951c6300SRichard Henderson         if (!is64) {
1882951c6300SRichard Henderson             op &= ~MO_SIGN;
1883951c6300SRichard Henderson         }
1884951c6300SRichard Henderson         break;
1885951c6300SRichard Henderson     case MO_64:
1886951c6300SRichard Henderson         if (!is64) {
1887951c6300SRichard Henderson             tcg_abort();
1888951c6300SRichard Henderson         }
1889951c6300SRichard Henderson         break;
1890951c6300SRichard Henderson     }
1891951c6300SRichard Henderson     if (st) {
1892951c6300SRichard Henderson         op &= ~MO_SIGN;
1893951c6300SRichard Henderson     }
1894951c6300SRichard Henderson     return op;
1895951c6300SRichard Henderson }
1896951c6300SRichard Henderson 
1897c45cb8bbSRichard Henderson static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
1898c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
1899951c6300SRichard Henderson {
190059227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
1901951c6300SRichard Henderson #if TARGET_LONG_BITS == 32
190259227d5dSRichard Henderson     tcg_gen_op3i_i32(opc, val, addr, oi);
1903951c6300SRichard Henderson #else
1904c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
190559227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
1906c45cb8bbSRichard Henderson     } else {
190759227d5dSRichard Henderson         tcg_gen_op3(&tcg_ctx, opc, GET_TCGV_I32(val), GET_TCGV_I64(addr), oi);
1908c45cb8bbSRichard Henderson     }
1909951c6300SRichard Henderson #endif
1910c45cb8bbSRichard Henderson }
1911c45cb8bbSRichard Henderson 
1912c45cb8bbSRichard Henderson static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
1913c45cb8bbSRichard Henderson                          TCGMemOp memop, TCGArg idx)
1914c45cb8bbSRichard Henderson {
191559227d5dSRichard Henderson     TCGMemOpIdx oi = make_memop_idx(memop, idx);
1916c45cb8bbSRichard Henderson #if TARGET_LONG_BITS == 32
1917c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
191859227d5dSRichard Henderson         tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
1919c45cb8bbSRichard Henderson     } else {
192059227d5dSRichard Henderson         tcg_gen_op3(&tcg_ctx, opc, GET_TCGV_I64(val), GET_TCGV_I32(addr), oi);
1921c45cb8bbSRichard Henderson     }
1922c45cb8bbSRichard Henderson #else
1923c45cb8bbSRichard Henderson     if (TCG_TARGET_REG_BITS == 32) {
192459227d5dSRichard Henderson         tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
192559227d5dSRichard Henderson                          TCGV_LOW(addr), TCGV_HIGH(addr), oi);
1926c45cb8bbSRichard Henderson     } else {
192759227d5dSRichard Henderson         tcg_gen_op3i_i64(opc, val, addr, oi);
1928c45cb8bbSRichard Henderson     }
1929c45cb8bbSRichard Henderson #endif
1930c45cb8bbSRichard Henderson }
1931951c6300SRichard Henderson 
1932951c6300SRichard Henderson void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1933951c6300SRichard Henderson {
1934951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
1935dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1936dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
1937c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
1938951c6300SRichard Henderson }
1939951c6300SRichard Henderson 
1940951c6300SRichard Henderson void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1941951c6300SRichard Henderson {
1942951c6300SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 1);
1943dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1944dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
1945c45cb8bbSRichard Henderson     gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
1946951c6300SRichard Henderson }
1947951c6300SRichard Henderson 
1948951c6300SRichard Henderson void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1949951c6300SRichard Henderson {
19503a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
1951951c6300SRichard Henderson         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
1952951c6300SRichard Henderson         if (memop & MO_SIGN) {
1953951c6300SRichard Henderson             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
1954951c6300SRichard Henderson         } else {
1955951c6300SRichard Henderson             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
1956951c6300SRichard Henderson         }
1957951c6300SRichard Henderson         return;
1958951c6300SRichard Henderson     }
1959951c6300SRichard Henderson 
1960c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
1961dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1962dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 0));
1963c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
1964951c6300SRichard Henderson }
1965951c6300SRichard Henderson 
1966951c6300SRichard Henderson void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1967951c6300SRichard Henderson {
19683a13c3f3SRichard Henderson     if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
1969951c6300SRichard Henderson         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
1970951c6300SRichard Henderson         return;
1971951c6300SRichard Henderson     }
1972951c6300SRichard Henderson 
1973c45cb8bbSRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 1);
1974dcdaadb6SLluís Vilanova     trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1975dcdaadb6SLluís Vilanova                                addr, trace_mem_get_info(memop, 1));
1976c45cb8bbSRichard Henderson     gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
1977951c6300SRichard Henderson }
1978c482cb11SRichard Henderson 
1979c482cb11SRichard Henderson static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc)
1980c482cb11SRichard Henderson {
1981c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
1982c482cb11SRichard Henderson     case MO_SB:
1983c482cb11SRichard Henderson         tcg_gen_ext8s_i32(ret, val);
1984c482cb11SRichard Henderson         break;
1985c482cb11SRichard Henderson     case MO_UB:
1986c482cb11SRichard Henderson         tcg_gen_ext8u_i32(ret, val);
1987c482cb11SRichard Henderson         break;
1988c482cb11SRichard Henderson     case MO_SW:
1989c482cb11SRichard Henderson         tcg_gen_ext16s_i32(ret, val);
1990c482cb11SRichard Henderson         break;
1991c482cb11SRichard Henderson     case MO_UW:
1992c482cb11SRichard Henderson         tcg_gen_ext16u_i32(ret, val);
1993c482cb11SRichard Henderson         break;
1994c482cb11SRichard Henderson     default:
1995c482cb11SRichard Henderson         tcg_gen_mov_i32(ret, val);
1996c482cb11SRichard Henderson         break;
1997c482cb11SRichard Henderson     }
1998c482cb11SRichard Henderson }
1999c482cb11SRichard Henderson 
2000c482cb11SRichard Henderson static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, TCGMemOp opc)
2001c482cb11SRichard Henderson {
2002c482cb11SRichard Henderson     switch (opc & MO_SSIZE) {
2003c482cb11SRichard Henderson     case MO_SB:
2004c482cb11SRichard Henderson         tcg_gen_ext8s_i64(ret, val);
2005c482cb11SRichard Henderson         break;
2006c482cb11SRichard Henderson     case MO_UB:
2007c482cb11SRichard Henderson         tcg_gen_ext8u_i64(ret, val);
2008c482cb11SRichard Henderson         break;
2009c482cb11SRichard Henderson     case MO_SW:
2010c482cb11SRichard Henderson         tcg_gen_ext16s_i64(ret, val);
2011c482cb11SRichard Henderson         break;
2012c482cb11SRichard Henderson     case MO_UW:
2013c482cb11SRichard Henderson         tcg_gen_ext16u_i64(ret, val);
2014c482cb11SRichard Henderson         break;
2015c482cb11SRichard Henderson     case MO_SL:
2016c482cb11SRichard Henderson         tcg_gen_ext32s_i64(ret, val);
2017c482cb11SRichard Henderson         break;
2018c482cb11SRichard Henderson     case MO_UL:
2019c482cb11SRichard Henderson         tcg_gen_ext32u_i64(ret, val);
2020c482cb11SRichard Henderson         break;
2021c482cb11SRichard Henderson     default:
2022c482cb11SRichard Henderson         tcg_gen_mov_i64(ret, val);
2023c482cb11SRichard Henderson         break;
2024c482cb11SRichard Henderson     }
2025c482cb11SRichard Henderson }
2026c482cb11SRichard Henderson 
2027c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2028c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
2029c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32, TCGv_i32);
2030c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
2031c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i64, TCGv_i32);
2032c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
2033c482cb11SRichard Henderson                                   TCGv_i32, TCGv_i32);
2034c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
2035c482cb11SRichard Henderson                                   TCGv_i64, TCGv_i32);
2036c482cb11SRichard Henderson #else
2037c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
2038c482cb11SRichard Henderson typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
2039c482cb11SRichard Henderson typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
2040c482cb11SRichard Henderson typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
2041c482cb11SRichard Henderson #endif
2042c482cb11SRichard Henderson 
2043*df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2044*df79b996SRichard Henderson # define WITH_ATOMIC64(X) X,
2045*df79b996SRichard Henderson #else
2046*df79b996SRichard Henderson # define WITH_ATOMIC64(X)
2047*df79b996SRichard Henderson #endif
2048*df79b996SRichard Henderson 
2049c482cb11SRichard Henderson static void * const table_cmpxchg[16] = {
2050c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_cmpxchgb,
2051c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
2052c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
2053c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
2054c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
2055*df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
2056*df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
2057c482cb11SRichard Henderson };
2058c482cb11SRichard Henderson 
2059c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
2060c482cb11SRichard Henderson                                 TCGv_i32 newv, TCGArg idx, TCGMemOp memop)
2061c482cb11SRichard Henderson {
2062c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2063c482cb11SRichard Henderson 
2064c482cb11SRichard Henderson     if (!parallel_cpus) {
2065c482cb11SRichard Henderson         TCGv_i32 t1 = tcg_temp_new_i32();
2066c482cb11SRichard Henderson         TCGv_i32 t2 = tcg_temp_new_i32();
2067c482cb11SRichard Henderson 
2068c482cb11SRichard Henderson         tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
2069c482cb11SRichard Henderson 
2070c482cb11SRichard Henderson         tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2071c482cb11SRichard Henderson         tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
2072c482cb11SRichard Henderson         tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2073c482cb11SRichard Henderson         tcg_temp_free_i32(t2);
2074c482cb11SRichard Henderson 
2075c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2076c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, t1, memop);
2077c482cb11SRichard Henderson         } else {
2078c482cb11SRichard Henderson             tcg_gen_mov_i32(retv, t1);
2079c482cb11SRichard Henderson         }
2080c482cb11SRichard Henderson         tcg_temp_free_i32(t1);
2081c482cb11SRichard Henderson     } else {
2082c482cb11SRichard Henderson         gen_atomic_cx_i32 gen;
2083c482cb11SRichard Henderson 
2084c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2085c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2086c482cb11SRichard Henderson 
2087c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2088c482cb11SRichard Henderson         {
2089c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2090c482cb11SRichard Henderson             gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv, oi);
2091c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2092c482cb11SRichard Henderson         }
2093c482cb11SRichard Henderson #else
2094c482cb11SRichard Henderson         gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv);
2095c482cb11SRichard Henderson #endif
2096c482cb11SRichard Henderson 
2097c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2098c482cb11SRichard Henderson             tcg_gen_ext_i32(retv, retv, memop);
2099c482cb11SRichard Henderson         }
2100c482cb11SRichard Henderson     }
2101c482cb11SRichard Henderson }
2102c482cb11SRichard Henderson 
2103c482cb11SRichard Henderson void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
2104c482cb11SRichard Henderson                                 TCGv_i64 newv, TCGArg idx, TCGMemOp memop)
2105c482cb11SRichard Henderson {
2106c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2107c482cb11SRichard Henderson 
2108c482cb11SRichard Henderson     if (!parallel_cpus) {
2109c482cb11SRichard Henderson         TCGv_i64 t1 = tcg_temp_new_i64();
2110c482cb11SRichard Henderson         TCGv_i64 t2 = tcg_temp_new_i64();
2111c482cb11SRichard Henderson 
2112c482cb11SRichard Henderson         tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
2113c482cb11SRichard Henderson 
2114c482cb11SRichard Henderson         tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2115c482cb11SRichard Henderson         tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
2116c482cb11SRichard Henderson         tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2117c482cb11SRichard Henderson         tcg_temp_free_i64(t2);
2118c482cb11SRichard Henderson 
2119c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2120c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, t1, memop);
2121c482cb11SRichard Henderson         } else {
2122c482cb11SRichard Henderson             tcg_gen_mov_i64(retv, t1);
2123c482cb11SRichard Henderson         }
2124c482cb11SRichard Henderson         tcg_temp_free_i64(t1);
2125c482cb11SRichard Henderson     } else if ((memop & MO_SIZE) == MO_64) {
2126*df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2127c482cb11SRichard Henderson         gen_atomic_cx_i64 gen;
2128c482cb11SRichard Henderson 
2129c482cb11SRichard Henderson         gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2130c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2131c482cb11SRichard Henderson 
2132c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2133c482cb11SRichard Henderson         {
2134c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
2135c482cb11SRichard Henderson             gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv, oi);
2136c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2137c482cb11SRichard Henderson         }
2138c482cb11SRichard Henderson #else
2139c482cb11SRichard Henderson         gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv);
2140c482cb11SRichard Henderson #endif
2141*df79b996SRichard Henderson #else
2142*df79b996SRichard Henderson         gen_helper_exit_atomic(tcg_ctx.tcg_env);
2143*df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
2144c482cb11SRichard Henderson     } else {
2145c482cb11SRichard Henderson         TCGv_i32 c32 = tcg_temp_new_i32();
2146c482cb11SRichard Henderson         TCGv_i32 n32 = tcg_temp_new_i32();
2147c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
2148c482cb11SRichard Henderson 
2149c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(c32, cmpv);
2150c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(n32, newv);
2151c482cb11SRichard Henderson         tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
2152c482cb11SRichard Henderson         tcg_temp_free_i32(c32);
2153c482cb11SRichard Henderson         tcg_temp_free_i32(n32);
2154c482cb11SRichard Henderson 
2155c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(retv, r32);
2156c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
2157c482cb11SRichard Henderson 
2158c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2159c482cb11SRichard Henderson             tcg_gen_ext_i64(retv, retv, memop);
2160c482cb11SRichard Henderson         }
2161c482cb11SRichard Henderson     }
2162c482cb11SRichard Henderson }
2163c482cb11SRichard Henderson 
2164c482cb11SRichard Henderson static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2165c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2166c482cb11SRichard Henderson                                 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
2167c482cb11SRichard Henderson {
2168c482cb11SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
2169c482cb11SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
2170c482cb11SRichard Henderson 
2171c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2172c482cb11SRichard Henderson 
2173c482cb11SRichard Henderson     tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2174c482cb11SRichard Henderson     gen(t2, t1, val);
2175c482cb11SRichard Henderson     tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2176c482cb11SRichard Henderson 
2177c482cb11SRichard Henderson     tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
2178c482cb11SRichard Henderson     tcg_temp_free_i32(t1);
2179c482cb11SRichard Henderson     tcg_temp_free_i32(t2);
2180c482cb11SRichard Henderson }
2181c482cb11SRichard Henderson 
2182c482cb11SRichard Henderson static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2183c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2184c482cb11SRichard Henderson {
2185c482cb11SRichard Henderson     gen_atomic_op_i32 gen;
2186c482cb11SRichard Henderson 
2187c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 0, 0);
2188c482cb11SRichard Henderson 
2189c482cb11SRichard Henderson     gen = table[memop & (MO_SIZE | MO_BSWAP)];
2190c482cb11SRichard Henderson     tcg_debug_assert(gen != NULL);
2191c482cb11SRichard Henderson 
2192c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2193c482cb11SRichard Henderson     {
2194c482cb11SRichard Henderson         TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2195c482cb11SRichard Henderson         gen(ret, tcg_ctx.tcg_env, addr, val, oi);
2196c482cb11SRichard Henderson         tcg_temp_free_i32(oi);
2197c482cb11SRichard Henderson     }
2198c482cb11SRichard Henderson #else
2199c482cb11SRichard Henderson     gen(ret, tcg_ctx.tcg_env, addr, val);
2200c482cb11SRichard Henderson #endif
2201c482cb11SRichard Henderson 
2202c482cb11SRichard Henderson     if (memop & MO_SIGN) {
2203c482cb11SRichard Henderson         tcg_gen_ext_i32(ret, ret, memop);
2204c482cb11SRichard Henderson     }
2205c482cb11SRichard Henderson }
2206c482cb11SRichard Henderson 
2207c482cb11SRichard Henderson static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2208c482cb11SRichard Henderson                                 TCGArg idx, TCGMemOp memop, bool new_val,
2209c482cb11SRichard Henderson                                 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
2210c482cb11SRichard Henderson {
2211c482cb11SRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
2212c482cb11SRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
2213c482cb11SRichard Henderson 
2214c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2215c482cb11SRichard Henderson 
2216c482cb11SRichard Henderson     tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2217c482cb11SRichard Henderson     gen(t2, t1, val);
2218c482cb11SRichard Henderson     tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2219c482cb11SRichard Henderson 
2220c482cb11SRichard Henderson     tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
2221c482cb11SRichard Henderson     tcg_temp_free_i64(t1);
2222c482cb11SRichard Henderson     tcg_temp_free_i64(t2);
2223c482cb11SRichard Henderson }
2224c482cb11SRichard Henderson 
2225c482cb11SRichard Henderson static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2226c482cb11SRichard Henderson                              TCGArg idx, TCGMemOp memop, void * const table[])
2227c482cb11SRichard Henderson {
2228c482cb11SRichard Henderson     memop = tcg_canonicalize_memop(memop, 1, 0);
2229c482cb11SRichard Henderson 
2230c482cb11SRichard Henderson     if ((memop & MO_SIZE) == MO_64) {
2231*df79b996SRichard Henderson #ifdef CONFIG_ATOMIC64
2232c482cb11SRichard Henderson         gen_atomic_op_i64 gen;
2233c482cb11SRichard Henderson 
2234c482cb11SRichard Henderson         gen = table[memop & (MO_SIZE | MO_BSWAP)];
2235c482cb11SRichard Henderson         tcg_debug_assert(gen != NULL);
2236c482cb11SRichard Henderson 
2237c482cb11SRichard Henderson #ifdef CONFIG_SOFTMMU
2238c482cb11SRichard Henderson         {
2239c482cb11SRichard Henderson             TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2240c482cb11SRichard Henderson             gen(ret, tcg_ctx.tcg_env, addr, val, oi);
2241c482cb11SRichard Henderson             tcg_temp_free_i32(oi);
2242c482cb11SRichard Henderson         }
2243c482cb11SRichard Henderson #else
2244c482cb11SRichard Henderson         gen(ret, tcg_ctx.tcg_env, addr, val);
2245c482cb11SRichard Henderson #endif
2246*df79b996SRichard Henderson #else
2247*df79b996SRichard Henderson         gen_helper_exit_atomic(tcg_ctx.tcg_env);
2248*df79b996SRichard Henderson #endif /* CONFIG_ATOMIC64 */
2249c482cb11SRichard Henderson     } else {
2250c482cb11SRichard Henderson         TCGv_i32 v32 = tcg_temp_new_i32();
2251c482cb11SRichard Henderson         TCGv_i32 r32 = tcg_temp_new_i32();
2252c482cb11SRichard Henderson 
2253c482cb11SRichard Henderson         tcg_gen_extrl_i64_i32(v32, val);
2254c482cb11SRichard Henderson         do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
2255c482cb11SRichard Henderson         tcg_temp_free_i32(v32);
2256c482cb11SRichard Henderson 
2257c482cb11SRichard Henderson         tcg_gen_extu_i32_i64(ret, r32);
2258c482cb11SRichard Henderson         tcg_temp_free_i32(r32);
2259c482cb11SRichard Henderson 
2260c482cb11SRichard Henderson         if (memop & MO_SIGN) {
2261c482cb11SRichard Henderson             tcg_gen_ext_i64(ret, ret, memop);
2262c482cb11SRichard Henderson         }
2263c482cb11SRichard Henderson     }
2264c482cb11SRichard Henderson }
2265c482cb11SRichard Henderson 
2266c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(NAME, OP, NEW)                                \
2267c482cb11SRichard Henderson static void * const table_##NAME[16] = {                                \
2268c482cb11SRichard Henderson     [MO_8] = gen_helper_atomic_##NAME##b,                               \
2269c482cb11SRichard Henderson     [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,                   \
2270c482cb11SRichard Henderson     [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,                   \
2271c482cb11SRichard Henderson     [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le,                   \
2272c482cb11SRichard Henderson     [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be,                   \
2273*df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le)     \
2274*df79b996SRichard Henderson     WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be)     \
2275c482cb11SRichard Henderson };                                                                      \
2276c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i32                                        \
2277c482cb11SRichard Henderson     (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \
2278c482cb11SRichard Henderson {                                                                       \
2279c482cb11SRichard Henderson     if (parallel_cpus) {                                                \
2280c482cb11SRichard Henderson         do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME);     \
2281c482cb11SRichard Henderson     } else {                                                            \
2282c482cb11SRichard Henderson         do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW,            \
2283c482cb11SRichard Henderson                             tcg_gen_##OP##_i32);                        \
2284c482cb11SRichard Henderson     }                                                                   \
2285c482cb11SRichard Henderson }                                                                       \
2286c482cb11SRichard Henderson void tcg_gen_atomic_##NAME##_i64                                        \
2287c482cb11SRichard Henderson     (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \
2288c482cb11SRichard Henderson {                                                                       \
2289c482cb11SRichard Henderson     if (parallel_cpus) {                                                \
2290c482cb11SRichard Henderson         do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME);     \
2291c482cb11SRichard Henderson     } else {                                                            \
2292c482cb11SRichard Henderson         do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW,            \
2293c482cb11SRichard Henderson                             tcg_gen_##OP##_i64);                        \
2294c482cb11SRichard Henderson     }                                                                   \
2295c482cb11SRichard Henderson }
2296c482cb11SRichard Henderson 
2297c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add, add, 0)
2298c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and, and, 0)
2299c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or, or, 0)
2300c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
2301c482cb11SRichard Henderson 
2302c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch, add, 1)
2303c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch, and, 1)
2304c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch, or, 1)
2305c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
2306c482cb11SRichard Henderson 
2307c482cb11SRichard Henderson static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
2308c482cb11SRichard Henderson {
2309c482cb11SRichard Henderson     tcg_gen_mov_i32(r, b);
2310c482cb11SRichard Henderson }
2311c482cb11SRichard Henderson 
2312c482cb11SRichard Henderson static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
2313c482cb11SRichard Henderson {
2314c482cb11SRichard Henderson     tcg_gen_mov_i64(r, b);
2315c482cb11SRichard Henderson }
2316c482cb11SRichard Henderson 
2317c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xchg, mov2, 0)
2318c482cb11SRichard Henderson 
2319c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
2320