Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream-mttcg' into staging
[qemu/ar7.git] / tcg / tcg-op.c
blobbb2bfeef3c339b065465004f1df7a354cf906487
1 /*
2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "qemu-common.h"
27 #include "cpu.h"
28 #include "exec/exec-all.h"
29 #include "tcg.h"
30 #include "tcg-op.h"
31 #include "trace-tcg.h"
32 #include "trace/mem.h"
34 /* Reduce the number of ifdefs below. This assumes that all uses of
35 TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
36 the compiler can eliminate. */
37 #if TCG_TARGET_REG_BITS == 64
38 extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
39 extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
40 #define TCGV_LOW TCGV_LOW_link_error
41 #define TCGV_HIGH TCGV_HIGH_link_error
42 #endif
44 /* Note that this is optimized for sequential allocation during translate.
45 Up to and including filling in the forward link immediately. We'll do
46 proper termination of the end of the list after we finish translation. */
48 static void tcg_emit_op(TCGContext *ctx, TCGOpcode opc, int args)
50 int oi = ctx->gen_next_op_idx;
51 int ni = oi + 1;
52 int pi = oi - 1;
54 tcg_debug_assert(oi < OPC_BUF_SIZE);
55 ctx->gen_op_buf[0].prev = oi;
56 ctx->gen_next_op_idx = ni;
58 ctx->gen_op_buf[oi] = (TCGOp){
59 .opc = opc,
60 .args = args,
61 .prev = pi,
62 .next = ni
66 void tcg_gen_op1(TCGContext *ctx, TCGOpcode opc, TCGArg a1)
68 int pi = ctx->gen_next_parm_idx;
70 tcg_debug_assert(pi + 1 <= OPPARAM_BUF_SIZE);
71 ctx->gen_next_parm_idx = pi + 1;
72 ctx->gen_opparam_buf[pi] = a1;
74 tcg_emit_op(ctx, opc, pi);
77 void tcg_gen_op2(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2)
79 int pi = ctx->gen_next_parm_idx;
81 tcg_debug_assert(pi + 2 <= OPPARAM_BUF_SIZE);
82 ctx->gen_next_parm_idx = pi + 2;
83 ctx->gen_opparam_buf[pi + 0] = a1;
84 ctx->gen_opparam_buf[pi + 1] = a2;
86 tcg_emit_op(ctx, opc, pi);
89 void tcg_gen_op3(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
90 TCGArg a2, TCGArg a3)
92 int pi = ctx->gen_next_parm_idx;
94 tcg_debug_assert(pi + 3 <= OPPARAM_BUF_SIZE);
95 ctx->gen_next_parm_idx = pi + 3;
96 ctx->gen_opparam_buf[pi + 0] = a1;
97 ctx->gen_opparam_buf[pi + 1] = a2;
98 ctx->gen_opparam_buf[pi + 2] = a3;
100 tcg_emit_op(ctx, opc, pi);
103 void tcg_gen_op4(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
104 TCGArg a2, TCGArg a3, TCGArg a4)
106 int pi = ctx->gen_next_parm_idx;
108 tcg_debug_assert(pi + 4 <= OPPARAM_BUF_SIZE);
109 ctx->gen_next_parm_idx = pi + 4;
110 ctx->gen_opparam_buf[pi + 0] = a1;
111 ctx->gen_opparam_buf[pi + 1] = a2;
112 ctx->gen_opparam_buf[pi + 2] = a3;
113 ctx->gen_opparam_buf[pi + 3] = a4;
115 tcg_emit_op(ctx, opc, pi);
118 void tcg_gen_op5(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
119 TCGArg a2, TCGArg a3, TCGArg a4, TCGArg a5)
121 int pi = ctx->gen_next_parm_idx;
123 tcg_debug_assert(pi + 5 <= OPPARAM_BUF_SIZE);
124 ctx->gen_next_parm_idx = pi + 5;
125 ctx->gen_opparam_buf[pi + 0] = a1;
126 ctx->gen_opparam_buf[pi + 1] = a2;
127 ctx->gen_opparam_buf[pi + 2] = a3;
128 ctx->gen_opparam_buf[pi + 3] = a4;
129 ctx->gen_opparam_buf[pi + 4] = a5;
131 tcg_emit_op(ctx, opc, pi);
134 void tcg_gen_op6(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2,
135 TCGArg a3, TCGArg a4, TCGArg a5, TCGArg a6)
137 int pi = ctx->gen_next_parm_idx;
139 tcg_debug_assert(pi + 6 <= OPPARAM_BUF_SIZE);
140 ctx->gen_next_parm_idx = pi + 6;
141 ctx->gen_opparam_buf[pi + 0] = a1;
142 ctx->gen_opparam_buf[pi + 1] = a2;
143 ctx->gen_opparam_buf[pi + 2] = a3;
144 ctx->gen_opparam_buf[pi + 3] = a4;
145 ctx->gen_opparam_buf[pi + 4] = a5;
146 ctx->gen_opparam_buf[pi + 5] = a6;
148 tcg_emit_op(ctx, opc, pi);
151 void tcg_gen_mb(TCGBar mb_type)
153 if (parallel_cpus) {
154 tcg_gen_op1(&tcg_ctx, INDEX_op_mb, mb_type);
158 /* 32 bit ops */
160 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
162 /* some cases can be optimized here */
163 if (arg2 == 0) {
164 tcg_gen_mov_i32(ret, arg1);
165 } else {
166 TCGv_i32 t0 = tcg_const_i32(arg2);
167 tcg_gen_add_i32(ret, arg1, t0);
168 tcg_temp_free_i32(t0);
172 void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
174 if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
175 /* Don't recurse with tcg_gen_neg_i32. */
176 tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
177 } else {
178 TCGv_i32 t0 = tcg_const_i32(arg1);
179 tcg_gen_sub_i32(ret, t0, arg2);
180 tcg_temp_free_i32(t0);
184 void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
186 /* some cases can be optimized here */
187 if (arg2 == 0) {
188 tcg_gen_mov_i32(ret, arg1);
189 } else {
190 TCGv_i32 t0 = tcg_const_i32(arg2);
191 tcg_gen_sub_i32(ret, arg1, t0);
192 tcg_temp_free_i32(t0);
196 void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
198 TCGv_i32 t0;
199 /* Some cases can be optimized here. */
200 switch (arg2) {
201 case 0:
202 tcg_gen_movi_i32(ret, 0);
203 return;
204 case 0xffffffffu:
205 tcg_gen_mov_i32(ret, arg1);
206 return;
207 case 0xffu:
208 /* Don't recurse with tcg_gen_ext8u_i32. */
209 if (TCG_TARGET_HAS_ext8u_i32) {
210 tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
211 return;
213 break;
214 case 0xffffu:
215 if (TCG_TARGET_HAS_ext16u_i32) {
216 tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
217 return;
219 break;
221 t0 = tcg_const_i32(arg2);
222 tcg_gen_and_i32(ret, arg1, t0);
223 tcg_temp_free_i32(t0);
226 void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
228 /* Some cases can be optimized here. */
229 if (arg2 == -1) {
230 tcg_gen_movi_i32(ret, -1);
231 } else if (arg2 == 0) {
232 tcg_gen_mov_i32(ret, arg1);
233 } else {
234 TCGv_i32 t0 = tcg_const_i32(arg2);
235 tcg_gen_or_i32(ret, arg1, t0);
236 tcg_temp_free_i32(t0);
240 void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
242 /* Some cases can be optimized here. */
243 if (arg2 == 0) {
244 tcg_gen_mov_i32(ret, arg1);
245 } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) {
246 /* Don't recurse with tcg_gen_not_i32. */
247 tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
248 } else {
249 TCGv_i32 t0 = tcg_const_i32(arg2);
250 tcg_gen_xor_i32(ret, arg1, t0);
251 tcg_temp_free_i32(t0);
255 void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
257 tcg_debug_assert(arg2 < 32);
258 if (arg2 == 0) {
259 tcg_gen_mov_i32(ret, arg1);
260 } else {
261 TCGv_i32 t0 = tcg_const_i32(arg2);
262 tcg_gen_shl_i32(ret, arg1, t0);
263 tcg_temp_free_i32(t0);
267 void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
269 tcg_debug_assert(arg2 < 32);
270 if (arg2 == 0) {
271 tcg_gen_mov_i32(ret, arg1);
272 } else {
273 TCGv_i32 t0 = tcg_const_i32(arg2);
274 tcg_gen_shr_i32(ret, arg1, t0);
275 tcg_temp_free_i32(t0);
279 void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
281 tcg_debug_assert(arg2 < 32);
282 if (arg2 == 0) {
283 tcg_gen_mov_i32(ret, arg1);
284 } else {
285 TCGv_i32 t0 = tcg_const_i32(arg2);
286 tcg_gen_sar_i32(ret, arg1, t0);
287 tcg_temp_free_i32(t0);
291 void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *l)
293 if (cond == TCG_COND_ALWAYS) {
294 tcg_gen_br(l);
295 } else if (cond != TCG_COND_NEVER) {
296 tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_arg(l));
300 void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *l)
302 if (cond == TCG_COND_ALWAYS) {
303 tcg_gen_br(l);
304 } else if (cond != TCG_COND_NEVER) {
305 TCGv_i32 t0 = tcg_const_i32(arg2);
306 tcg_gen_brcond_i32(cond, arg1, t0, l);
307 tcg_temp_free_i32(t0);
311 void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
312 TCGv_i32 arg1, TCGv_i32 arg2)
314 if (cond == TCG_COND_ALWAYS) {
315 tcg_gen_movi_i32(ret, 1);
316 } else if (cond == TCG_COND_NEVER) {
317 tcg_gen_movi_i32(ret, 0);
318 } else {
319 tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
323 void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
324 TCGv_i32 arg1, int32_t arg2)
326 TCGv_i32 t0 = tcg_const_i32(arg2);
327 tcg_gen_setcond_i32(cond, ret, arg1, t0);
328 tcg_temp_free_i32(t0);
331 void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
333 TCGv_i32 t0 = tcg_const_i32(arg2);
334 tcg_gen_mul_i32(ret, arg1, t0);
335 tcg_temp_free_i32(t0);
338 void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
340 if (TCG_TARGET_HAS_div_i32) {
341 tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
342 } else if (TCG_TARGET_HAS_div2_i32) {
343 TCGv_i32 t0 = tcg_temp_new_i32();
344 tcg_gen_sari_i32(t0, arg1, 31);
345 tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
346 tcg_temp_free_i32(t0);
347 } else {
348 gen_helper_div_i32(ret, arg1, arg2);
352 void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
354 if (TCG_TARGET_HAS_rem_i32) {
355 tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
356 } else if (TCG_TARGET_HAS_div_i32) {
357 TCGv_i32 t0 = tcg_temp_new_i32();
358 tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
359 tcg_gen_mul_i32(t0, t0, arg2);
360 tcg_gen_sub_i32(ret, arg1, t0);
361 tcg_temp_free_i32(t0);
362 } else if (TCG_TARGET_HAS_div2_i32) {
363 TCGv_i32 t0 = tcg_temp_new_i32();
364 tcg_gen_sari_i32(t0, arg1, 31);
365 tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
366 tcg_temp_free_i32(t0);
367 } else {
368 gen_helper_rem_i32(ret, arg1, arg2);
372 void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
374 if (TCG_TARGET_HAS_div_i32) {
375 tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
376 } else if (TCG_TARGET_HAS_div2_i32) {
377 TCGv_i32 t0 = tcg_temp_new_i32();
378 tcg_gen_movi_i32(t0, 0);
379 tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
380 tcg_temp_free_i32(t0);
381 } else {
382 gen_helper_divu_i32(ret, arg1, arg2);
386 void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
388 if (TCG_TARGET_HAS_rem_i32) {
389 tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
390 } else if (TCG_TARGET_HAS_div_i32) {
391 TCGv_i32 t0 = tcg_temp_new_i32();
392 tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
393 tcg_gen_mul_i32(t0, t0, arg2);
394 tcg_gen_sub_i32(ret, arg1, t0);
395 tcg_temp_free_i32(t0);
396 } else if (TCG_TARGET_HAS_div2_i32) {
397 TCGv_i32 t0 = tcg_temp_new_i32();
398 tcg_gen_movi_i32(t0, 0);
399 tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
400 tcg_temp_free_i32(t0);
401 } else {
402 gen_helper_remu_i32(ret, arg1, arg2);
406 void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
408 if (TCG_TARGET_HAS_andc_i32) {
409 tcg_gen_op3_i32(INDEX_op_andc_i32, ret, arg1, arg2);
410 } else {
411 TCGv_i32 t0 = tcg_temp_new_i32();
412 tcg_gen_not_i32(t0, arg2);
413 tcg_gen_and_i32(ret, arg1, t0);
414 tcg_temp_free_i32(t0);
418 void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
420 if (TCG_TARGET_HAS_eqv_i32) {
421 tcg_gen_op3_i32(INDEX_op_eqv_i32, ret, arg1, arg2);
422 } else {
423 tcg_gen_xor_i32(ret, arg1, arg2);
424 tcg_gen_not_i32(ret, ret);
428 void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
430 if (TCG_TARGET_HAS_nand_i32) {
431 tcg_gen_op3_i32(INDEX_op_nand_i32, ret, arg1, arg2);
432 } else {
433 tcg_gen_and_i32(ret, arg1, arg2);
434 tcg_gen_not_i32(ret, ret);
438 void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
440 if (TCG_TARGET_HAS_nor_i32) {
441 tcg_gen_op3_i32(INDEX_op_nor_i32, ret, arg1, arg2);
442 } else {
443 tcg_gen_or_i32(ret, arg1, arg2);
444 tcg_gen_not_i32(ret, ret);
448 void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
450 if (TCG_TARGET_HAS_orc_i32) {
451 tcg_gen_op3_i32(INDEX_op_orc_i32, ret, arg1, arg2);
452 } else {
453 TCGv_i32 t0 = tcg_temp_new_i32();
454 tcg_gen_not_i32(t0, arg2);
455 tcg_gen_or_i32(ret, arg1, t0);
456 tcg_temp_free_i32(t0);
460 void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
462 if (TCG_TARGET_HAS_rot_i32) {
463 tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
464 } else {
465 TCGv_i32 t0, t1;
467 t0 = tcg_temp_new_i32();
468 t1 = tcg_temp_new_i32();
469 tcg_gen_shl_i32(t0, arg1, arg2);
470 tcg_gen_subfi_i32(t1, 32, arg2);
471 tcg_gen_shr_i32(t1, arg1, t1);
472 tcg_gen_or_i32(ret, t0, t1);
473 tcg_temp_free_i32(t0);
474 tcg_temp_free_i32(t1);
478 void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
480 tcg_debug_assert(arg2 < 32);
481 /* some cases can be optimized here */
482 if (arg2 == 0) {
483 tcg_gen_mov_i32(ret, arg1);
484 } else if (TCG_TARGET_HAS_rot_i32) {
485 TCGv_i32 t0 = tcg_const_i32(arg2);
486 tcg_gen_rotl_i32(ret, arg1, t0);
487 tcg_temp_free_i32(t0);
488 } else {
489 TCGv_i32 t0, t1;
490 t0 = tcg_temp_new_i32();
491 t1 = tcg_temp_new_i32();
492 tcg_gen_shli_i32(t0, arg1, arg2);
493 tcg_gen_shri_i32(t1, arg1, 32 - arg2);
494 tcg_gen_or_i32(ret, t0, t1);
495 tcg_temp_free_i32(t0);
496 tcg_temp_free_i32(t1);
500 void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
502 if (TCG_TARGET_HAS_rot_i32) {
503 tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
504 } else {
505 TCGv_i32 t0, t1;
507 t0 = tcg_temp_new_i32();
508 t1 = tcg_temp_new_i32();
509 tcg_gen_shr_i32(t0, arg1, arg2);
510 tcg_gen_subfi_i32(t1, 32, arg2);
511 tcg_gen_shl_i32(t1, arg1, t1);
512 tcg_gen_or_i32(ret, t0, t1);
513 tcg_temp_free_i32(t0);
514 tcg_temp_free_i32(t1);
518 void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
520 tcg_debug_assert(arg2 < 32);
521 /* some cases can be optimized here */
522 if (arg2 == 0) {
523 tcg_gen_mov_i32(ret, arg1);
524 } else {
525 tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
529 void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
530 unsigned int ofs, unsigned int len)
532 uint32_t mask;
533 TCGv_i32 t1;
535 tcg_debug_assert(ofs < 32);
536 tcg_debug_assert(len <= 32);
537 tcg_debug_assert(ofs + len <= 32);
539 if (ofs == 0 && len == 32) {
540 tcg_gen_mov_i32(ret, arg2);
541 return;
543 if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) {
544 tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
545 return;
548 mask = (1u << len) - 1;
549 t1 = tcg_temp_new_i32();
551 if (ofs + len < 32) {
552 tcg_gen_andi_i32(t1, arg2, mask);
553 tcg_gen_shli_i32(t1, t1, ofs);
554 } else {
555 tcg_gen_shli_i32(t1, arg2, ofs);
557 tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
558 tcg_gen_or_i32(ret, ret, t1);
560 tcg_temp_free_i32(t1);
563 void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
564 TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2)
566 if (cond == TCG_COND_ALWAYS) {
567 tcg_gen_mov_i32(ret, v1);
568 } else if (cond == TCG_COND_NEVER) {
569 tcg_gen_mov_i32(ret, v2);
570 } else if (TCG_TARGET_HAS_movcond_i32) {
571 tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
572 } else {
573 TCGv_i32 t0 = tcg_temp_new_i32();
574 TCGv_i32 t1 = tcg_temp_new_i32();
575 tcg_gen_setcond_i32(cond, t0, c1, c2);
576 tcg_gen_neg_i32(t0, t0);
577 tcg_gen_and_i32(t1, v1, t0);
578 tcg_gen_andc_i32(ret, v2, t0);
579 tcg_gen_or_i32(ret, ret, t1);
580 tcg_temp_free_i32(t0);
581 tcg_temp_free_i32(t1);
585 void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
586 TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
588 if (TCG_TARGET_HAS_add2_i32) {
589 tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh);
590 } else {
591 TCGv_i64 t0 = tcg_temp_new_i64();
592 TCGv_i64 t1 = tcg_temp_new_i64();
593 tcg_gen_concat_i32_i64(t0, al, ah);
594 tcg_gen_concat_i32_i64(t1, bl, bh);
595 tcg_gen_add_i64(t0, t0, t1);
596 tcg_gen_extr_i64_i32(rl, rh, t0);
597 tcg_temp_free_i64(t0);
598 tcg_temp_free_i64(t1);
602 void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
603 TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh)
605 if (TCG_TARGET_HAS_sub2_i32) {
606 tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh);
607 } else {
608 TCGv_i64 t0 = tcg_temp_new_i64();
609 TCGv_i64 t1 = tcg_temp_new_i64();
610 tcg_gen_concat_i32_i64(t0, al, ah);
611 tcg_gen_concat_i32_i64(t1, bl, bh);
612 tcg_gen_sub_i64(t0, t0, t1);
613 tcg_gen_extr_i64_i32(rl, rh, t0);
614 tcg_temp_free_i64(t0);
615 tcg_temp_free_i64(t1);
619 void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
621 if (TCG_TARGET_HAS_mulu2_i32) {
622 tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2);
623 } else if (TCG_TARGET_HAS_muluh_i32) {
624 TCGv_i32 t = tcg_temp_new_i32();
625 tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
626 tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
627 tcg_gen_mov_i32(rl, t);
628 tcg_temp_free_i32(t);
629 } else {
630 TCGv_i64 t0 = tcg_temp_new_i64();
631 TCGv_i64 t1 = tcg_temp_new_i64();
632 tcg_gen_extu_i32_i64(t0, arg1);
633 tcg_gen_extu_i32_i64(t1, arg2);
634 tcg_gen_mul_i64(t0, t0, t1);
635 tcg_gen_extr_i64_i32(rl, rh, t0);
636 tcg_temp_free_i64(t0);
637 tcg_temp_free_i64(t1);
641 void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
643 if (TCG_TARGET_HAS_muls2_i32) {
644 tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2);
645 } else if (TCG_TARGET_HAS_mulsh_i32) {
646 TCGv_i32 t = tcg_temp_new_i32();
647 tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2);
648 tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
649 tcg_gen_mov_i32(rl, t);
650 tcg_temp_free_i32(t);
651 } else if (TCG_TARGET_REG_BITS == 32) {
652 TCGv_i32 t0 = tcg_temp_new_i32();
653 TCGv_i32 t1 = tcg_temp_new_i32();
654 TCGv_i32 t2 = tcg_temp_new_i32();
655 TCGv_i32 t3 = tcg_temp_new_i32();
656 tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
657 /* Adjust for negative inputs. */
658 tcg_gen_sari_i32(t2, arg1, 31);
659 tcg_gen_sari_i32(t3, arg2, 31);
660 tcg_gen_and_i32(t2, t2, arg2);
661 tcg_gen_and_i32(t3, t3, arg1);
662 tcg_gen_sub_i32(rh, t1, t2);
663 tcg_gen_sub_i32(rh, rh, t3);
664 tcg_gen_mov_i32(rl, t0);
665 tcg_temp_free_i32(t0);
666 tcg_temp_free_i32(t1);
667 tcg_temp_free_i32(t2);
668 tcg_temp_free_i32(t3);
669 } else {
670 TCGv_i64 t0 = tcg_temp_new_i64();
671 TCGv_i64 t1 = tcg_temp_new_i64();
672 tcg_gen_ext_i32_i64(t0, arg1);
673 tcg_gen_ext_i32_i64(t1, arg2);
674 tcg_gen_mul_i64(t0, t0, t1);
675 tcg_gen_extr_i64_i32(rl, rh, t0);
676 tcg_temp_free_i64(t0);
677 tcg_temp_free_i64(t1);
681 void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
683 if (TCG_TARGET_HAS_ext8s_i32) {
684 tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
685 } else {
686 tcg_gen_shli_i32(ret, arg, 24);
687 tcg_gen_sari_i32(ret, ret, 24);
691 void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
693 if (TCG_TARGET_HAS_ext16s_i32) {
694 tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
695 } else {
696 tcg_gen_shli_i32(ret, arg, 16);
697 tcg_gen_sari_i32(ret, ret, 16);
701 void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
703 if (TCG_TARGET_HAS_ext8u_i32) {
704 tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg);
705 } else {
706 tcg_gen_andi_i32(ret, arg, 0xffu);
710 void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
712 if (TCG_TARGET_HAS_ext16u_i32) {
713 tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg);
714 } else {
715 tcg_gen_andi_i32(ret, arg, 0xffffu);
719 /* Note: we assume the two high bytes are set to zero */
720 void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
722 if (TCG_TARGET_HAS_bswap16_i32) {
723 tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
724 } else {
725 TCGv_i32 t0 = tcg_temp_new_i32();
727 tcg_gen_ext8u_i32(t0, arg);
728 tcg_gen_shli_i32(t0, t0, 8);
729 tcg_gen_shri_i32(ret, arg, 8);
730 tcg_gen_or_i32(ret, ret, t0);
731 tcg_temp_free_i32(t0);
735 void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
737 if (TCG_TARGET_HAS_bswap32_i32) {
738 tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
739 } else {
740 TCGv_i32 t0, t1;
741 t0 = tcg_temp_new_i32();
742 t1 = tcg_temp_new_i32();
744 tcg_gen_shli_i32(t0, arg, 24);
746 tcg_gen_andi_i32(t1, arg, 0x0000ff00);
747 tcg_gen_shli_i32(t1, t1, 8);
748 tcg_gen_or_i32(t0, t0, t1);
750 tcg_gen_shri_i32(t1, arg, 8);
751 tcg_gen_andi_i32(t1, t1, 0x0000ff00);
752 tcg_gen_or_i32(t0, t0, t1);
754 tcg_gen_shri_i32(t1, arg, 24);
755 tcg_gen_or_i32(ret, t0, t1);
756 tcg_temp_free_i32(t0);
757 tcg_temp_free_i32(t1);
761 /* 64-bit ops */
763 #if TCG_TARGET_REG_BITS == 32
764 /* These are all inline for TCG_TARGET_REG_BITS == 64. */
766 void tcg_gen_discard_i64(TCGv_i64 arg)
768 tcg_gen_discard_i32(TCGV_LOW(arg));
769 tcg_gen_discard_i32(TCGV_HIGH(arg));
772 void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
774 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
775 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
778 void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
780 tcg_gen_movi_i32(TCGV_LOW(ret), arg);
781 tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
784 void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
786 tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
787 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
790 void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
792 tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
793 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), 31);
796 void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
798 tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
799 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
802 void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
804 tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
805 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
808 void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
810 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
811 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
814 void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
816 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
817 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
820 void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
822 /* Since arg2 and ret have different types,
823 they cannot be the same temporary */
824 #ifdef HOST_WORDS_BIGENDIAN
825 tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
826 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
827 #else
828 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
829 tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
830 #endif
833 void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
835 #ifdef HOST_WORDS_BIGENDIAN
836 tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
837 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
838 #else
839 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
840 tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
841 #endif
844 void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
846 tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
847 tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
850 void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
852 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
853 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
856 void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
858 tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
859 tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
862 void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
864 gen_helper_shl_i64(ret, arg1, arg2);
867 void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
869 gen_helper_shr_i64(ret, arg1, arg2);
872 void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
874 gen_helper_sar_i64(ret, arg1, arg2);
877 void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
879 TCGv_i64 t0;
880 TCGv_i32 t1;
882 t0 = tcg_temp_new_i64();
883 t1 = tcg_temp_new_i32();
885 tcg_gen_mulu2_i32(TCGV_LOW(t0), TCGV_HIGH(t0),
886 TCGV_LOW(arg1), TCGV_LOW(arg2));
888 tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
889 tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
890 tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
891 tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
893 tcg_gen_mov_i64(ret, t0);
894 tcg_temp_free_i64(t0);
895 tcg_temp_free_i32(t1);
897 #endif /* TCG_TARGET_REG_SIZE == 32 */
899 void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
901 /* some cases can be optimized here */
902 if (arg2 == 0) {
903 tcg_gen_mov_i64(ret, arg1);
904 } else {
905 TCGv_i64 t0 = tcg_const_i64(arg2);
906 tcg_gen_add_i64(ret, arg1, t0);
907 tcg_temp_free_i64(t0);
911 void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
913 if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
914 /* Don't recurse with tcg_gen_neg_i64. */
915 tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
916 } else {
917 TCGv_i64 t0 = tcg_const_i64(arg1);
918 tcg_gen_sub_i64(ret, t0, arg2);
919 tcg_temp_free_i64(t0);
923 void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
925 /* some cases can be optimized here */
926 if (arg2 == 0) {
927 tcg_gen_mov_i64(ret, arg1);
928 } else {
929 TCGv_i64 t0 = tcg_const_i64(arg2);
930 tcg_gen_sub_i64(ret, arg1, t0);
931 tcg_temp_free_i64(t0);
935 void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
937 TCGv_i64 t0;
939 if (TCG_TARGET_REG_BITS == 32) {
940 tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
941 tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
942 return;
945 /* Some cases can be optimized here. */
946 switch (arg2) {
947 case 0:
948 tcg_gen_movi_i64(ret, 0);
949 return;
950 case 0xffffffffffffffffull:
951 tcg_gen_mov_i64(ret, arg1);
952 return;
953 case 0xffull:
954 /* Don't recurse with tcg_gen_ext8u_i64. */
955 if (TCG_TARGET_HAS_ext8u_i64) {
956 tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
957 return;
959 break;
960 case 0xffffu:
961 if (TCG_TARGET_HAS_ext16u_i64) {
962 tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
963 return;
965 break;
966 case 0xffffffffull:
967 if (TCG_TARGET_HAS_ext32u_i64) {
968 tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
969 return;
971 break;
973 t0 = tcg_const_i64(arg2);
974 tcg_gen_and_i64(ret, arg1, t0);
975 tcg_temp_free_i64(t0);
978 void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
980 if (TCG_TARGET_REG_BITS == 32) {
981 tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
982 tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
983 return;
985 /* Some cases can be optimized here. */
986 if (arg2 == -1) {
987 tcg_gen_movi_i64(ret, -1);
988 } else if (arg2 == 0) {
989 tcg_gen_mov_i64(ret, arg1);
990 } else {
991 TCGv_i64 t0 = tcg_const_i64(arg2);
992 tcg_gen_or_i64(ret, arg1, t0);
993 tcg_temp_free_i64(t0);
997 void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
999 if (TCG_TARGET_REG_BITS == 32) {
1000 tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
1001 tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
1002 return;
1004 /* Some cases can be optimized here. */
1005 if (arg2 == 0) {
1006 tcg_gen_mov_i64(ret, arg1);
1007 } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) {
1008 /* Don't recurse with tcg_gen_not_i64. */
1009 tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
1010 } else {
1011 TCGv_i64 t0 = tcg_const_i64(arg2);
1012 tcg_gen_xor_i64(ret, arg1, t0);
1013 tcg_temp_free_i64(t0);
1017 static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
1018 unsigned c, bool right, bool arith)
1020 tcg_debug_assert(c < 64);
1021 if (c == 0) {
1022 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1023 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1024 } else if (c >= 32) {
1025 c -= 32;
1026 if (right) {
1027 if (arith) {
1028 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1029 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1030 } else {
1031 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1032 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1034 } else {
1035 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1036 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1038 } else {
1039 TCGv_i32 t0, t1;
1041 t0 = tcg_temp_new_i32();
1042 t1 = tcg_temp_new_i32();
1043 if (right) {
1044 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
1045 if (arith) {
1046 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
1047 } else {
1048 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
1050 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
1051 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
1052 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
1053 } else {
1054 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
1055 /* Note: ret can be the same as arg1, so we use t1 */
1056 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
1057 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1058 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
1059 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1061 tcg_temp_free_i32(t0);
1062 tcg_temp_free_i32(t1);
1066 void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1068 tcg_debug_assert(arg2 < 64);
1069 if (TCG_TARGET_REG_BITS == 32) {
1070 tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
1071 } else if (arg2 == 0) {
1072 tcg_gen_mov_i64(ret, arg1);
1073 } else {
1074 TCGv_i64 t0 = tcg_const_i64(arg2);
1075 tcg_gen_shl_i64(ret, arg1, t0);
1076 tcg_temp_free_i64(t0);
1080 void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1082 tcg_debug_assert(arg2 < 64);
1083 if (TCG_TARGET_REG_BITS == 32) {
1084 tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
1085 } else if (arg2 == 0) {
1086 tcg_gen_mov_i64(ret, arg1);
1087 } else {
1088 TCGv_i64 t0 = tcg_const_i64(arg2);
1089 tcg_gen_shr_i64(ret, arg1, t0);
1090 tcg_temp_free_i64(t0);
1094 void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1096 tcg_debug_assert(arg2 < 64);
1097 if (TCG_TARGET_REG_BITS == 32) {
1098 tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
1099 } else if (arg2 == 0) {
1100 tcg_gen_mov_i64(ret, arg1);
1101 } else {
1102 TCGv_i64 t0 = tcg_const_i64(arg2);
1103 tcg_gen_sar_i64(ret, arg1, t0);
1104 tcg_temp_free_i64(t0);
1108 void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *l)
1110 if (cond == TCG_COND_ALWAYS) {
1111 tcg_gen_br(l);
1112 } else if (cond != TCG_COND_NEVER) {
1113 if (TCG_TARGET_REG_BITS == 32) {
1114 tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, TCGV_LOW(arg1),
1115 TCGV_HIGH(arg1), TCGV_LOW(arg2),
1116 TCGV_HIGH(arg2), cond, label_arg(l));
1117 } else {
1118 tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
1119 label_arg(l));
1124 void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
1126 if (cond == TCG_COND_ALWAYS) {
1127 tcg_gen_br(l);
1128 } else if (cond != TCG_COND_NEVER) {
1129 TCGv_i64 t0 = tcg_const_i64(arg2);
1130 tcg_gen_brcond_i64(cond, arg1, t0, l);
1131 tcg_temp_free_i64(t0);
1135 void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
1136 TCGv_i64 arg1, TCGv_i64 arg2)
1138 if (cond == TCG_COND_ALWAYS) {
1139 tcg_gen_movi_i64(ret, 1);
1140 } else if (cond == TCG_COND_NEVER) {
1141 tcg_gen_movi_i64(ret, 0);
1142 } else {
1143 if (TCG_TARGET_REG_BITS == 32) {
1144 tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
1145 TCGV_LOW(arg1), TCGV_HIGH(arg1),
1146 TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
1147 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1148 } else {
1149 tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
1154 void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
1155 TCGv_i64 arg1, int64_t arg2)
1157 TCGv_i64 t0 = tcg_const_i64(arg2);
1158 tcg_gen_setcond_i64(cond, ret, arg1, t0);
1159 tcg_temp_free_i64(t0);
1162 void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
1164 TCGv_i64 t0 = tcg_const_i64(arg2);
1165 tcg_gen_mul_i64(ret, arg1, t0);
1166 tcg_temp_free_i64(t0);
1169 void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1171 if (TCG_TARGET_HAS_div_i64) {
1172 tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
1173 } else if (TCG_TARGET_HAS_div2_i64) {
1174 TCGv_i64 t0 = tcg_temp_new_i64();
1175 tcg_gen_sari_i64(t0, arg1, 63);
1176 tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
1177 tcg_temp_free_i64(t0);
1178 } else {
1179 gen_helper_div_i64(ret, arg1, arg2);
1183 void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1185 if (TCG_TARGET_HAS_rem_i64) {
1186 tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
1187 } else if (TCG_TARGET_HAS_div_i64) {
1188 TCGv_i64 t0 = tcg_temp_new_i64();
1189 tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
1190 tcg_gen_mul_i64(t0, t0, arg2);
1191 tcg_gen_sub_i64(ret, arg1, t0);
1192 tcg_temp_free_i64(t0);
1193 } else if (TCG_TARGET_HAS_div2_i64) {
1194 TCGv_i64 t0 = tcg_temp_new_i64();
1195 tcg_gen_sari_i64(t0, arg1, 63);
1196 tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
1197 tcg_temp_free_i64(t0);
1198 } else {
1199 gen_helper_rem_i64(ret, arg1, arg2);
1203 void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1205 if (TCG_TARGET_HAS_div_i64) {
1206 tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
1207 } else if (TCG_TARGET_HAS_div2_i64) {
1208 TCGv_i64 t0 = tcg_temp_new_i64();
1209 tcg_gen_movi_i64(t0, 0);
1210 tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
1211 tcg_temp_free_i64(t0);
1212 } else {
1213 gen_helper_divu_i64(ret, arg1, arg2);
1217 void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1219 if (TCG_TARGET_HAS_rem_i64) {
1220 tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
1221 } else if (TCG_TARGET_HAS_div_i64) {
1222 TCGv_i64 t0 = tcg_temp_new_i64();
1223 tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
1224 tcg_gen_mul_i64(t0, t0, arg2);
1225 tcg_gen_sub_i64(ret, arg1, t0);
1226 tcg_temp_free_i64(t0);
1227 } else if (TCG_TARGET_HAS_div2_i64) {
1228 TCGv_i64 t0 = tcg_temp_new_i64();
1229 tcg_gen_movi_i64(t0, 0);
1230 tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
1231 tcg_temp_free_i64(t0);
1232 } else {
1233 gen_helper_remu_i64(ret, arg1, arg2);
1237 void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
1239 if (TCG_TARGET_REG_BITS == 32) {
1240 tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1241 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1242 } else if (TCG_TARGET_HAS_ext8s_i64) {
1243 tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
1244 } else {
1245 tcg_gen_shli_i64(ret, arg, 56);
1246 tcg_gen_sari_i64(ret, ret, 56);
1250 void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
1252 if (TCG_TARGET_REG_BITS == 32) {
1253 tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1254 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1255 } else if (TCG_TARGET_HAS_ext16s_i64) {
1256 tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
1257 } else {
1258 tcg_gen_shli_i64(ret, arg, 48);
1259 tcg_gen_sari_i64(ret, ret, 48);
1263 void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
1265 if (TCG_TARGET_REG_BITS == 32) {
1266 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1267 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1268 } else if (TCG_TARGET_HAS_ext32s_i64) {
1269 tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
1270 } else {
1271 tcg_gen_shli_i64(ret, arg, 32);
1272 tcg_gen_sari_i64(ret, ret, 32);
1276 void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
1278 if (TCG_TARGET_REG_BITS == 32) {
1279 tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1280 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1281 } else if (TCG_TARGET_HAS_ext8u_i64) {
1282 tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg);
1283 } else {
1284 tcg_gen_andi_i64(ret, arg, 0xffu);
1288 void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
1290 if (TCG_TARGET_REG_BITS == 32) {
1291 tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1292 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1293 } else if (TCG_TARGET_HAS_ext16u_i64) {
1294 tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg);
1295 } else {
1296 tcg_gen_andi_i64(ret, arg, 0xffffu);
1300 void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
1302 if (TCG_TARGET_REG_BITS == 32) {
1303 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1304 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1305 } else if (TCG_TARGET_HAS_ext32u_i64) {
1306 tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg);
1307 } else {
1308 tcg_gen_andi_i64(ret, arg, 0xffffffffu);
1312 /* Note: we assume the six high bytes are set to zero */
1313 void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
1315 if (TCG_TARGET_REG_BITS == 32) {
1316 tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1317 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1318 } else if (TCG_TARGET_HAS_bswap16_i64) {
1319 tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
1320 } else {
1321 TCGv_i64 t0 = tcg_temp_new_i64();
1323 tcg_gen_ext8u_i64(t0, arg);
1324 tcg_gen_shli_i64(t0, t0, 8);
1325 tcg_gen_shri_i64(ret, arg, 8);
1326 tcg_gen_or_i64(ret, ret, t0);
1327 tcg_temp_free_i64(t0);
1331 /* Note: we assume the four high bytes are set to zero */
1332 void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
1334 if (TCG_TARGET_REG_BITS == 32) {
1335 tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1336 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1337 } else if (TCG_TARGET_HAS_bswap32_i64) {
1338 tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
1339 } else {
1340 TCGv_i64 t0, t1;
1341 t0 = tcg_temp_new_i64();
1342 t1 = tcg_temp_new_i64();
1344 tcg_gen_shli_i64(t0, arg, 24);
1345 tcg_gen_ext32u_i64(t0, t0);
1347 tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1348 tcg_gen_shli_i64(t1, t1, 8);
1349 tcg_gen_or_i64(t0, t0, t1);
1351 tcg_gen_shri_i64(t1, arg, 8);
1352 tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1353 tcg_gen_or_i64(t0, t0, t1);
1355 tcg_gen_shri_i64(t1, arg, 24);
1356 tcg_gen_or_i64(ret, t0, t1);
1357 tcg_temp_free_i64(t0);
1358 tcg_temp_free_i64(t1);
1362 void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
1364 if (TCG_TARGET_REG_BITS == 32) {
1365 TCGv_i32 t0, t1;
1366 t0 = tcg_temp_new_i32();
1367 t1 = tcg_temp_new_i32();
1369 tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
1370 tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
1371 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
1372 tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
1373 tcg_temp_free_i32(t0);
1374 tcg_temp_free_i32(t1);
1375 } else if (TCG_TARGET_HAS_bswap64_i64) {
1376 tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
1377 } else {
1378 TCGv_i64 t0 = tcg_temp_new_i64();
1379 TCGv_i64 t1 = tcg_temp_new_i64();
1381 tcg_gen_shli_i64(t0, arg, 56);
1383 tcg_gen_andi_i64(t1, arg, 0x0000ff00);
1384 tcg_gen_shli_i64(t1, t1, 40);
1385 tcg_gen_or_i64(t0, t0, t1);
1387 tcg_gen_andi_i64(t1, arg, 0x00ff0000);
1388 tcg_gen_shli_i64(t1, t1, 24);
1389 tcg_gen_or_i64(t0, t0, t1);
1391 tcg_gen_andi_i64(t1, arg, 0xff000000);
1392 tcg_gen_shli_i64(t1, t1, 8);
1393 tcg_gen_or_i64(t0, t0, t1);
1395 tcg_gen_shri_i64(t1, arg, 8);
1396 tcg_gen_andi_i64(t1, t1, 0xff000000);
1397 tcg_gen_or_i64(t0, t0, t1);
1399 tcg_gen_shri_i64(t1, arg, 24);
1400 tcg_gen_andi_i64(t1, t1, 0x00ff0000);
1401 tcg_gen_or_i64(t0, t0, t1);
1403 tcg_gen_shri_i64(t1, arg, 40);
1404 tcg_gen_andi_i64(t1, t1, 0x0000ff00);
1405 tcg_gen_or_i64(t0, t0, t1);
1407 tcg_gen_shri_i64(t1, arg, 56);
1408 tcg_gen_or_i64(ret, t0, t1);
1409 tcg_temp_free_i64(t0);
1410 tcg_temp_free_i64(t1);
1414 void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
1416 if (TCG_TARGET_REG_BITS == 32) {
1417 tcg_gen_not_i32(TCGV_LOW(ret), TCGV_LOW(arg));
1418 tcg_gen_not_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
1419 } else if (TCG_TARGET_HAS_not_i64) {
1420 tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
1421 } else {
1422 tcg_gen_xori_i64(ret, arg, -1);
1426 void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1428 if (TCG_TARGET_REG_BITS == 32) {
1429 tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1430 tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1431 } else if (TCG_TARGET_HAS_andc_i64) {
1432 tcg_gen_op3_i64(INDEX_op_andc_i64, ret, arg1, arg2);
1433 } else {
1434 TCGv_i64 t0 = tcg_temp_new_i64();
1435 tcg_gen_not_i64(t0, arg2);
1436 tcg_gen_and_i64(ret, arg1, t0);
1437 tcg_temp_free_i64(t0);
1441 void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1443 if (TCG_TARGET_REG_BITS == 32) {
1444 tcg_gen_eqv_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1445 tcg_gen_eqv_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1446 } else if (TCG_TARGET_HAS_eqv_i64) {
1447 tcg_gen_op3_i64(INDEX_op_eqv_i64, ret, arg1, arg2);
1448 } else {
1449 tcg_gen_xor_i64(ret, arg1, arg2);
1450 tcg_gen_not_i64(ret, ret);
1454 void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1456 if (TCG_TARGET_REG_BITS == 32) {
1457 tcg_gen_nand_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1458 tcg_gen_nand_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1459 } else if (TCG_TARGET_HAS_nand_i64) {
1460 tcg_gen_op3_i64(INDEX_op_nand_i64, ret, arg1, arg2);
1461 } else {
1462 tcg_gen_and_i64(ret, arg1, arg2);
1463 tcg_gen_not_i64(ret, ret);
1467 void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1469 if (TCG_TARGET_REG_BITS == 32) {
1470 tcg_gen_nor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1471 tcg_gen_nor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1472 } else if (TCG_TARGET_HAS_nor_i64) {
1473 tcg_gen_op3_i64(INDEX_op_nor_i64, ret, arg1, arg2);
1474 } else {
1475 tcg_gen_or_i64(ret, arg1, arg2);
1476 tcg_gen_not_i64(ret, ret);
1480 void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1482 if (TCG_TARGET_REG_BITS == 32) {
1483 tcg_gen_orc_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
1484 tcg_gen_orc_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
1485 } else if (TCG_TARGET_HAS_orc_i64) {
1486 tcg_gen_op3_i64(INDEX_op_orc_i64, ret, arg1, arg2);
1487 } else {
1488 TCGv_i64 t0 = tcg_temp_new_i64();
1489 tcg_gen_not_i64(t0, arg2);
1490 tcg_gen_or_i64(ret, arg1, t0);
1491 tcg_temp_free_i64(t0);
1495 void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1497 if (TCG_TARGET_HAS_rot_i64) {
1498 tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
1499 } else {
1500 TCGv_i64 t0, t1;
1501 t0 = tcg_temp_new_i64();
1502 t1 = tcg_temp_new_i64();
1503 tcg_gen_shl_i64(t0, arg1, arg2);
1504 tcg_gen_subfi_i64(t1, 64, arg2);
1505 tcg_gen_shr_i64(t1, arg1, t1);
1506 tcg_gen_or_i64(ret, t0, t1);
1507 tcg_temp_free_i64(t0);
1508 tcg_temp_free_i64(t1);
1512 void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1514 tcg_debug_assert(arg2 < 64);
1515 /* some cases can be optimized here */
1516 if (arg2 == 0) {
1517 tcg_gen_mov_i64(ret, arg1);
1518 } else if (TCG_TARGET_HAS_rot_i64) {
1519 TCGv_i64 t0 = tcg_const_i64(arg2);
1520 tcg_gen_rotl_i64(ret, arg1, t0);
1521 tcg_temp_free_i64(t0);
1522 } else {
1523 TCGv_i64 t0, t1;
1524 t0 = tcg_temp_new_i64();
1525 t1 = tcg_temp_new_i64();
1526 tcg_gen_shli_i64(t0, arg1, arg2);
1527 tcg_gen_shri_i64(t1, arg1, 64 - arg2);
1528 tcg_gen_or_i64(ret, t0, t1);
1529 tcg_temp_free_i64(t0);
1530 tcg_temp_free_i64(t1);
1534 void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1536 if (TCG_TARGET_HAS_rot_i64) {
1537 tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
1538 } else {
1539 TCGv_i64 t0, t1;
1540 t0 = tcg_temp_new_i64();
1541 t1 = tcg_temp_new_i64();
1542 tcg_gen_shr_i64(t0, arg1, arg2);
1543 tcg_gen_subfi_i64(t1, 64, arg2);
1544 tcg_gen_shl_i64(t1, arg1, t1);
1545 tcg_gen_or_i64(ret, t0, t1);
1546 tcg_temp_free_i64(t0);
1547 tcg_temp_free_i64(t1);
1551 void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
1553 tcg_debug_assert(arg2 < 64);
1554 /* some cases can be optimized here */
1555 if (arg2 == 0) {
1556 tcg_gen_mov_i64(ret, arg1);
1557 } else {
1558 tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
1562 void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
1563 unsigned int ofs, unsigned int len)
1565 uint64_t mask;
1566 TCGv_i64 t1;
1568 tcg_debug_assert(ofs < 64);
1569 tcg_debug_assert(len <= 64);
1570 tcg_debug_assert(ofs + len <= 64);
1572 if (ofs == 0 && len == 64) {
1573 tcg_gen_mov_i64(ret, arg2);
1574 return;
1576 if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) {
1577 tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
1578 return;
1581 if (TCG_TARGET_REG_BITS == 32) {
1582 if (ofs >= 32) {
1583 tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
1584 TCGV_LOW(arg2), ofs - 32, len);
1585 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
1586 return;
1588 if (ofs + len <= 32) {
1589 tcg_gen_deposit_i32(TCGV_LOW(ret), TCGV_LOW(arg1),
1590 TCGV_LOW(arg2), ofs, len);
1591 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
1592 return;
1596 mask = (1ull << len) - 1;
1597 t1 = tcg_temp_new_i64();
1599 if (ofs + len < 64) {
1600 tcg_gen_andi_i64(t1, arg2, mask);
1601 tcg_gen_shli_i64(t1, t1, ofs);
1602 } else {
1603 tcg_gen_shli_i64(t1, arg2, ofs);
1605 tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
1606 tcg_gen_or_i64(ret, ret, t1);
1608 tcg_temp_free_i64(t1);
1611 void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
1612 TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2)
1614 if (cond == TCG_COND_ALWAYS) {
1615 tcg_gen_mov_i64(ret, v1);
1616 } else if (cond == TCG_COND_NEVER) {
1617 tcg_gen_mov_i64(ret, v2);
1618 } else if (TCG_TARGET_REG_BITS == 32) {
1619 TCGv_i32 t0 = tcg_temp_new_i32();
1620 TCGv_i32 t1 = tcg_temp_new_i32();
1621 tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
1622 TCGV_LOW(c1), TCGV_HIGH(c1),
1623 TCGV_LOW(c2), TCGV_HIGH(c2), cond);
1625 if (TCG_TARGET_HAS_movcond_i32) {
1626 tcg_gen_movi_i32(t1, 0);
1627 tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
1628 TCGV_LOW(v1), TCGV_LOW(v2));
1629 tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
1630 TCGV_HIGH(v1), TCGV_HIGH(v2));
1631 } else {
1632 tcg_gen_neg_i32(t0, t0);
1634 tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
1635 tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
1636 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
1638 tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
1639 tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
1640 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
1642 tcg_temp_free_i32(t0);
1643 tcg_temp_free_i32(t1);
1644 } else if (TCG_TARGET_HAS_movcond_i64) {
1645 tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
1646 } else {
1647 TCGv_i64 t0 = tcg_temp_new_i64();
1648 TCGv_i64 t1 = tcg_temp_new_i64();
1649 tcg_gen_setcond_i64(cond, t0, c1, c2);
1650 tcg_gen_neg_i64(t0, t0);
1651 tcg_gen_and_i64(t1, v1, t0);
1652 tcg_gen_andc_i64(ret, v2, t0);
1653 tcg_gen_or_i64(ret, ret, t1);
1654 tcg_temp_free_i64(t0);
1655 tcg_temp_free_i64(t1);
1659 void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
1660 TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
1662 if (TCG_TARGET_HAS_add2_i64) {
1663 tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh);
1664 } else {
1665 TCGv_i64 t0 = tcg_temp_new_i64();
1666 TCGv_i64 t1 = tcg_temp_new_i64();
1667 tcg_gen_add_i64(t0, al, bl);
1668 tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al);
1669 tcg_gen_add_i64(rh, ah, bh);
1670 tcg_gen_add_i64(rh, rh, t1);
1671 tcg_gen_mov_i64(rl, t0);
1672 tcg_temp_free_i64(t0);
1673 tcg_temp_free_i64(t1);
1677 void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
1678 TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
1680 if (TCG_TARGET_HAS_sub2_i64) {
1681 tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh);
1682 } else {
1683 TCGv_i64 t0 = tcg_temp_new_i64();
1684 TCGv_i64 t1 = tcg_temp_new_i64();
1685 tcg_gen_sub_i64(t0, al, bl);
1686 tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl);
1687 tcg_gen_sub_i64(rh, ah, bh);
1688 tcg_gen_sub_i64(rh, rh, t1);
1689 tcg_gen_mov_i64(rl, t0);
1690 tcg_temp_free_i64(t0);
1691 tcg_temp_free_i64(t1);
1695 void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
1697 if (TCG_TARGET_HAS_mulu2_i64) {
1698 tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2);
1699 } else if (TCG_TARGET_HAS_muluh_i64) {
1700 TCGv_i64 t = tcg_temp_new_i64();
1701 tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
1702 tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
1703 tcg_gen_mov_i64(rl, t);
1704 tcg_temp_free_i64(t);
1705 } else {
1706 TCGv_i64 t0 = tcg_temp_new_i64();
1707 tcg_gen_mul_i64(t0, arg1, arg2);
1708 gen_helper_muluh_i64(rh, arg1, arg2);
1709 tcg_gen_mov_i64(rl, t0);
1710 tcg_temp_free_i64(t0);
1714 void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
1716 if (TCG_TARGET_HAS_muls2_i64) {
1717 tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2);
1718 } else if (TCG_TARGET_HAS_mulsh_i64) {
1719 TCGv_i64 t = tcg_temp_new_i64();
1720 tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2);
1721 tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
1722 tcg_gen_mov_i64(rl, t);
1723 tcg_temp_free_i64(t);
1724 } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
1725 TCGv_i64 t0 = tcg_temp_new_i64();
1726 TCGv_i64 t1 = tcg_temp_new_i64();
1727 TCGv_i64 t2 = tcg_temp_new_i64();
1728 TCGv_i64 t3 = tcg_temp_new_i64();
1729 tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
1730 /* Adjust for negative inputs. */
1731 tcg_gen_sari_i64(t2, arg1, 63);
1732 tcg_gen_sari_i64(t3, arg2, 63);
1733 tcg_gen_and_i64(t2, t2, arg2);
1734 tcg_gen_and_i64(t3, t3, arg1);
1735 tcg_gen_sub_i64(rh, t1, t2);
1736 tcg_gen_sub_i64(rh, rh, t3);
1737 tcg_gen_mov_i64(rl, t0);
1738 tcg_temp_free_i64(t0);
1739 tcg_temp_free_i64(t1);
1740 tcg_temp_free_i64(t2);
1741 tcg_temp_free_i64(t3);
1742 } else {
1743 TCGv_i64 t0 = tcg_temp_new_i64();
1744 tcg_gen_mul_i64(t0, arg1, arg2);
1745 gen_helper_mulsh_i64(rh, arg1, arg2);
1746 tcg_gen_mov_i64(rl, t0);
1747 tcg_temp_free_i64(t0);
1751 /* Size changing operations. */
1753 void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
1755 if (TCG_TARGET_REG_BITS == 32) {
1756 tcg_gen_mov_i32(ret, TCGV_LOW(arg));
1757 } else if (TCG_TARGET_HAS_extrl_i64_i32) {
1758 tcg_gen_op2(&tcg_ctx, INDEX_op_extrl_i64_i32,
1759 GET_TCGV_I32(ret), GET_TCGV_I64(arg));
1760 } else {
1761 tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
1765 void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
1767 if (TCG_TARGET_REG_BITS == 32) {
1768 tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
1769 } else if (TCG_TARGET_HAS_extrh_i64_i32) {
1770 tcg_gen_op2(&tcg_ctx, INDEX_op_extrh_i64_i32,
1771 GET_TCGV_I32(ret), GET_TCGV_I64(arg));
1772 } else {
1773 TCGv_i64 t = tcg_temp_new_i64();
1774 tcg_gen_shri_i64(t, arg, 32);
1775 tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(t)));
1776 tcg_temp_free_i64(t);
1780 void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
1782 if (TCG_TARGET_REG_BITS == 32) {
1783 tcg_gen_mov_i32(TCGV_LOW(ret), arg);
1784 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1785 } else {
1786 tcg_gen_op2(&tcg_ctx, INDEX_op_extu_i32_i64,
1787 GET_TCGV_I64(ret), GET_TCGV_I32(arg));
1791 void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
1793 if (TCG_TARGET_REG_BITS == 32) {
1794 tcg_gen_mov_i32(TCGV_LOW(ret), arg);
1795 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1796 } else {
1797 tcg_gen_op2(&tcg_ctx, INDEX_op_ext_i32_i64,
1798 GET_TCGV_I64(ret), GET_TCGV_I32(arg));
1802 void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
1804 TCGv_i64 tmp;
1806 if (TCG_TARGET_REG_BITS == 32) {
1807 tcg_gen_mov_i32(TCGV_LOW(dest), low);
1808 tcg_gen_mov_i32(TCGV_HIGH(dest), high);
1809 return;
1812 tmp = tcg_temp_new_i64();
1813 /* These extensions are only needed for type correctness.
1814 We may be able to do better given target specific information. */
1815 tcg_gen_extu_i32_i64(tmp, high);
1816 tcg_gen_extu_i32_i64(dest, low);
1817 /* If deposit is available, use it. Otherwise use the extra
1818 knowledge that we have of the zero-extensions above. */
1819 if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) {
1820 tcg_gen_deposit_i64(dest, dest, tmp, 32, 32);
1821 } else {
1822 tcg_gen_shli_i64(tmp, tmp, 32);
1823 tcg_gen_or_i64(dest, dest, tmp);
1825 tcg_temp_free_i64(tmp);
1828 void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
1830 if (TCG_TARGET_REG_BITS == 32) {
1831 tcg_gen_mov_i32(lo, TCGV_LOW(arg));
1832 tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
1833 } else {
1834 tcg_gen_extrl_i64_i32(lo, arg);
1835 tcg_gen_extrh_i64_i32(hi, arg);
1839 void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
1841 tcg_gen_ext32u_i64(lo, arg);
1842 tcg_gen_shri_i64(hi, arg, 32);
1845 /* QEMU specific operations. */
1847 void tcg_gen_goto_tb(unsigned idx)
1849 /* We only support two chained exits. */
1850 tcg_debug_assert(idx <= 1);
1851 #ifdef CONFIG_DEBUG_TCG
1852 /* Verify that we havn't seen this numbered exit before. */
1853 tcg_debug_assert((tcg_ctx.goto_tb_issue_mask & (1 << idx)) == 0);
1854 tcg_ctx.goto_tb_issue_mask |= 1 << idx;
1855 #endif
1856 tcg_gen_op1i(INDEX_op_goto_tb, idx);
1859 static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
1861 /* Trigger the asserts within as early as possible. */
1862 (void)get_alignment_bits(op);
1864 switch (op & MO_SIZE) {
1865 case MO_8:
1866 op &= ~MO_BSWAP;
1867 break;
1868 case MO_16:
1869 break;
1870 case MO_32:
1871 if (!is64) {
1872 op &= ~MO_SIGN;
1874 break;
1875 case MO_64:
1876 if (!is64) {
1877 tcg_abort();
1879 break;
1881 if (st) {
1882 op &= ~MO_SIGN;
1884 return op;
1887 static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
1888 TCGMemOp memop, TCGArg idx)
1890 TCGMemOpIdx oi = make_memop_idx(memop, idx);
1891 #if TARGET_LONG_BITS == 32
1892 tcg_gen_op3i_i32(opc, val, addr, oi);
1893 #else
1894 if (TCG_TARGET_REG_BITS == 32) {
1895 tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
1896 } else {
1897 tcg_gen_op3(&tcg_ctx, opc, GET_TCGV_I32(val), GET_TCGV_I64(addr), oi);
1899 #endif
1902 static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
1903 TCGMemOp memop, TCGArg idx)
1905 TCGMemOpIdx oi = make_memop_idx(memop, idx);
1906 #if TARGET_LONG_BITS == 32
1907 if (TCG_TARGET_REG_BITS == 32) {
1908 tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
1909 } else {
1910 tcg_gen_op3(&tcg_ctx, opc, GET_TCGV_I64(val), GET_TCGV_I32(addr), oi);
1912 #else
1913 if (TCG_TARGET_REG_BITS == 32) {
1914 tcg_gen_op5i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val),
1915 TCGV_LOW(addr), TCGV_HIGH(addr), oi);
1916 } else {
1917 tcg_gen_op3i_i64(opc, val, addr, oi);
1919 #endif
1922 void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1924 memop = tcg_canonicalize_memop(memop, 0, 0);
1925 trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1926 addr, trace_mem_get_info(memop, 0));
1927 gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
1930 void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1932 memop = tcg_canonicalize_memop(memop, 0, 1);
1933 trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1934 addr, trace_mem_get_info(memop, 1));
1935 gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
1938 void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1940 if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
1941 tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
1942 if (memop & MO_SIGN) {
1943 tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
1944 } else {
1945 tcg_gen_movi_i32(TCGV_HIGH(val), 0);
1947 return;
1950 memop = tcg_canonicalize_memop(memop, 1, 0);
1951 trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1952 addr, trace_mem_get_info(memop, 0));
1953 gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
1956 void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1958 if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
1959 tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
1960 return;
1963 memop = tcg_canonicalize_memop(memop, 1, 1);
1964 trace_guest_mem_before_tcg(tcg_ctx.cpu, tcg_ctx.tcg_env,
1965 addr, trace_mem_get_info(memop, 1));
1966 gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
1969 static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc)
1971 switch (opc & MO_SSIZE) {
1972 case MO_SB:
1973 tcg_gen_ext8s_i32(ret, val);
1974 break;
1975 case MO_UB:
1976 tcg_gen_ext8u_i32(ret, val);
1977 break;
1978 case MO_SW:
1979 tcg_gen_ext16s_i32(ret, val);
1980 break;
1981 case MO_UW:
1982 tcg_gen_ext16u_i32(ret, val);
1983 break;
1984 default:
1985 tcg_gen_mov_i32(ret, val);
1986 break;
1990 static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, TCGMemOp opc)
1992 switch (opc & MO_SSIZE) {
1993 case MO_SB:
1994 tcg_gen_ext8s_i64(ret, val);
1995 break;
1996 case MO_UB:
1997 tcg_gen_ext8u_i64(ret, val);
1998 break;
1999 case MO_SW:
2000 tcg_gen_ext16s_i64(ret, val);
2001 break;
2002 case MO_UW:
2003 tcg_gen_ext16u_i64(ret, val);
2004 break;
2005 case MO_SL:
2006 tcg_gen_ext32s_i64(ret, val);
2007 break;
2008 case MO_UL:
2009 tcg_gen_ext32u_i64(ret, val);
2010 break;
2011 default:
2012 tcg_gen_mov_i64(ret, val);
2013 break;
2017 #ifdef CONFIG_SOFTMMU
2018 typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
2019 TCGv_i32, TCGv_i32, TCGv_i32);
2020 typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
2021 TCGv_i64, TCGv_i64, TCGv_i32);
2022 typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv,
2023 TCGv_i32, TCGv_i32);
2024 typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
2025 TCGv_i64, TCGv_i32);
2026 #else
2027 typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
2028 typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
2029 typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
2030 typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
2031 #endif
2033 #ifdef CONFIG_ATOMIC64
2034 # define WITH_ATOMIC64(X) X,
2035 #else
2036 # define WITH_ATOMIC64(X)
2037 #endif
2039 static void * const table_cmpxchg[16] = {
2040 [MO_8] = gen_helper_atomic_cmpxchgb,
2041 [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
2042 [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
2043 [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
2044 [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
2045 WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
2046 WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
2049 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
2050 TCGv_i32 newv, TCGArg idx, TCGMemOp memop)
2052 memop = tcg_canonicalize_memop(memop, 0, 0);
2054 if (!parallel_cpus) {
2055 TCGv_i32 t1 = tcg_temp_new_i32();
2056 TCGv_i32 t2 = tcg_temp_new_i32();
2058 tcg_gen_ext_i32(t2, cmpv, memop & MO_SIZE);
2060 tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2061 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, t2, newv, t1);
2062 tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2063 tcg_temp_free_i32(t2);
2065 if (memop & MO_SIGN) {
2066 tcg_gen_ext_i32(retv, t1, memop);
2067 } else {
2068 tcg_gen_mov_i32(retv, t1);
2070 tcg_temp_free_i32(t1);
2071 } else {
2072 gen_atomic_cx_i32 gen;
2074 gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2075 tcg_debug_assert(gen != NULL);
2077 #ifdef CONFIG_SOFTMMU
2079 TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2080 gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv, oi);
2081 tcg_temp_free_i32(oi);
2083 #else
2084 gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv);
2085 #endif
2087 if (memop & MO_SIGN) {
2088 tcg_gen_ext_i32(retv, retv, memop);
2093 void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
2094 TCGv_i64 newv, TCGArg idx, TCGMemOp memop)
2096 memop = tcg_canonicalize_memop(memop, 1, 0);
2098 if (!parallel_cpus) {
2099 TCGv_i64 t1 = tcg_temp_new_i64();
2100 TCGv_i64 t2 = tcg_temp_new_i64();
2102 tcg_gen_ext_i64(t2, cmpv, memop & MO_SIZE);
2104 tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2105 tcg_gen_movcond_i64(TCG_COND_EQ, t2, t1, t2, newv, t1);
2106 tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2107 tcg_temp_free_i64(t2);
2109 if (memop & MO_SIGN) {
2110 tcg_gen_ext_i64(retv, t1, memop);
2111 } else {
2112 tcg_gen_mov_i64(retv, t1);
2114 tcg_temp_free_i64(t1);
2115 } else if ((memop & MO_SIZE) == MO_64) {
2116 #ifdef CONFIG_ATOMIC64
2117 gen_atomic_cx_i64 gen;
2119 gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
2120 tcg_debug_assert(gen != NULL);
2122 #ifdef CONFIG_SOFTMMU
2124 TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
2125 gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv, oi);
2126 tcg_temp_free_i32(oi);
2128 #else
2129 gen(retv, tcg_ctx.tcg_env, addr, cmpv, newv);
2130 #endif
2131 #else
2132 gen_helper_exit_atomic(tcg_ctx.tcg_env);
2133 #endif /* CONFIG_ATOMIC64 */
2134 } else {
2135 TCGv_i32 c32 = tcg_temp_new_i32();
2136 TCGv_i32 n32 = tcg_temp_new_i32();
2137 TCGv_i32 r32 = tcg_temp_new_i32();
2139 tcg_gen_extrl_i64_i32(c32, cmpv);
2140 tcg_gen_extrl_i64_i32(n32, newv);
2141 tcg_gen_atomic_cmpxchg_i32(r32, addr, c32, n32, idx, memop & ~MO_SIGN);
2142 tcg_temp_free_i32(c32);
2143 tcg_temp_free_i32(n32);
2145 tcg_gen_extu_i32_i64(retv, r32);
2146 tcg_temp_free_i32(r32);
2148 if (memop & MO_SIGN) {
2149 tcg_gen_ext_i64(retv, retv, memop);
2154 static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2155 TCGArg idx, TCGMemOp memop, bool new_val,
2156 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
2158 TCGv_i32 t1 = tcg_temp_new_i32();
2159 TCGv_i32 t2 = tcg_temp_new_i32();
2161 memop = tcg_canonicalize_memop(memop, 0, 0);
2163 tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN);
2164 gen(t2, t1, val);
2165 tcg_gen_qemu_st_i32(t2, addr, idx, memop);
2167 tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop);
2168 tcg_temp_free_i32(t1);
2169 tcg_temp_free_i32(t2);
2172 static void do_atomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val,
2173 TCGArg idx, TCGMemOp memop, void * const table[])
2175 gen_atomic_op_i32 gen;
2177 memop = tcg_canonicalize_memop(memop, 0, 0);
2179 gen = table[memop & (MO_SIZE | MO_BSWAP)];
2180 tcg_debug_assert(gen != NULL);
2182 #ifdef CONFIG_SOFTMMU
2184 TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2185 gen(ret, tcg_ctx.tcg_env, addr, val, oi);
2186 tcg_temp_free_i32(oi);
2188 #else
2189 gen(ret, tcg_ctx.tcg_env, addr, val);
2190 #endif
2192 if (memop & MO_SIGN) {
2193 tcg_gen_ext_i32(ret, ret, memop);
2197 static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2198 TCGArg idx, TCGMemOp memop, bool new_val,
2199 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
2201 TCGv_i64 t1 = tcg_temp_new_i64();
2202 TCGv_i64 t2 = tcg_temp_new_i64();
2204 memop = tcg_canonicalize_memop(memop, 1, 0);
2206 tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN);
2207 gen(t2, t1, val);
2208 tcg_gen_qemu_st_i64(t2, addr, idx, memop);
2210 tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop);
2211 tcg_temp_free_i64(t1);
2212 tcg_temp_free_i64(t2);
2215 static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val,
2216 TCGArg idx, TCGMemOp memop, void * const table[])
2218 memop = tcg_canonicalize_memop(memop, 1, 0);
2220 if ((memop & MO_SIZE) == MO_64) {
2221 #ifdef CONFIG_ATOMIC64
2222 gen_atomic_op_i64 gen;
2224 gen = table[memop & (MO_SIZE | MO_BSWAP)];
2225 tcg_debug_assert(gen != NULL);
2227 #ifdef CONFIG_SOFTMMU
2229 TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
2230 gen(ret, tcg_ctx.tcg_env, addr, val, oi);
2231 tcg_temp_free_i32(oi);
2233 #else
2234 gen(ret, tcg_ctx.tcg_env, addr, val);
2235 #endif
2236 #else
2237 gen_helper_exit_atomic(tcg_ctx.tcg_env);
2238 #endif /* CONFIG_ATOMIC64 */
2239 } else {
2240 TCGv_i32 v32 = tcg_temp_new_i32();
2241 TCGv_i32 r32 = tcg_temp_new_i32();
2243 tcg_gen_extrl_i64_i32(v32, val);
2244 do_atomic_op_i32(r32, addr, v32, idx, memop & ~MO_SIGN, table);
2245 tcg_temp_free_i32(v32);
2247 tcg_gen_extu_i32_i64(ret, r32);
2248 tcg_temp_free_i32(r32);
2250 if (memop & MO_SIGN) {
2251 tcg_gen_ext_i64(ret, ret, memop);
2256 #define GEN_ATOMIC_HELPER(NAME, OP, NEW) \
2257 static void * const table_##NAME[16] = { \
2258 [MO_8] = gen_helper_atomic_##NAME##b, \
2259 [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le, \
2260 [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be, \
2261 [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le, \
2262 [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be, \
2263 WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le) \
2264 WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be) \
2265 }; \
2266 void tcg_gen_atomic_##NAME##_i32 \
2267 (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \
2269 if (parallel_cpus) { \
2270 do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \
2271 } else { \
2272 do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \
2273 tcg_gen_##OP##_i32); \
2276 void tcg_gen_atomic_##NAME##_i64 \
2277 (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \
2279 if (parallel_cpus) { \
2280 do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \
2281 } else { \
2282 do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \
2283 tcg_gen_##OP##_i64); \
2287 GEN_ATOMIC_HELPER(fetch_add, add, 0)
2288 GEN_ATOMIC_HELPER(fetch_and, and, 0)
2289 GEN_ATOMIC_HELPER(fetch_or, or, 0)
2290 GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
2292 GEN_ATOMIC_HELPER(add_fetch, add, 1)
2293 GEN_ATOMIC_HELPER(and_fetch, and, 1)
2294 GEN_ATOMIC_HELPER(or_fetch, or, 1)
2295 GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
2297 static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
2299 tcg_gen_mov_i32(r, b);
2302 static void tcg_gen_mov2_i64(TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
2304 tcg_gen_mov_i64(r, b);
2307 GEN_ATOMIC_HELPER(xchg, mov2, 0)
2309 #undef GEN_ATOMIC_HELPER