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
25 #include "qemu/osdep.h"
26 #include "exec/exec-all.h"
28 #include "tcg/tcg-op.h"
29 #include "tcg/tcg-mo.h"
30 #include "exec/plugin-gen.h"
31 #include "tcg-internal.h"
34 void tcg_gen_op1(TCGOpcode opc
, TCGArg a1
)
36 TCGOp
*op
= tcg_emit_op(opc
, 1);
40 void tcg_gen_op2(TCGOpcode opc
, TCGArg a1
, TCGArg a2
)
42 TCGOp
*op
= tcg_emit_op(opc
, 2);
47 void tcg_gen_op3(TCGOpcode opc
, TCGArg a1
, TCGArg a2
, TCGArg a3
)
49 TCGOp
*op
= tcg_emit_op(opc
, 3);
55 void tcg_gen_op4(TCGOpcode opc
, TCGArg a1
, TCGArg a2
, TCGArg a3
, TCGArg a4
)
57 TCGOp
*op
= tcg_emit_op(opc
, 4);
64 void tcg_gen_op5(TCGOpcode opc
, TCGArg a1
, TCGArg a2
, TCGArg a3
,
67 TCGOp
*op
= tcg_emit_op(opc
, 5);
75 void tcg_gen_op6(TCGOpcode opc
, TCGArg a1
, TCGArg a2
, TCGArg a3
,
76 TCGArg a4
, TCGArg a5
, TCGArg a6
)
78 TCGOp
*op
= tcg_emit_op(opc
, 6);
87 void tcg_gen_mb(TCGBar mb_type
)
89 if (tcg_ctx
->gen_tb
->cflags
& CF_PARALLEL
) {
90 tcg_gen_op1(INDEX_op_mb
, mb_type
);
96 void tcg_gen_movi_i32(TCGv_i32 ret
, int32_t arg
)
98 tcg_gen_mov_i32(ret
, tcg_constant_i32(arg
));
101 void tcg_gen_addi_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
103 /* some cases can be optimized here */
105 tcg_gen_mov_i32(ret
, arg1
);
107 tcg_gen_add_i32(ret
, arg1
, tcg_constant_i32(arg2
));
111 void tcg_gen_subfi_i32(TCGv_i32 ret
, int32_t arg1
, TCGv_i32 arg2
)
113 if (arg1
== 0 && TCG_TARGET_HAS_neg_i32
) {
114 /* Don't recurse with tcg_gen_neg_i32. */
115 tcg_gen_op2_i32(INDEX_op_neg_i32
, ret
, arg2
);
117 tcg_gen_sub_i32(ret
, tcg_constant_i32(arg1
), arg2
);
121 void tcg_gen_subi_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
123 /* some cases can be optimized here */
125 tcg_gen_mov_i32(ret
, arg1
);
127 tcg_gen_sub_i32(ret
, arg1
, tcg_constant_i32(arg2
));
131 void tcg_gen_andi_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
133 /* Some cases can be optimized here. */
136 tcg_gen_movi_i32(ret
, 0);
139 tcg_gen_mov_i32(ret
, arg1
);
142 /* Don't recurse with tcg_gen_ext8u_i32. */
143 if (TCG_TARGET_HAS_ext8u_i32
) {
144 tcg_gen_op2_i32(INDEX_op_ext8u_i32
, ret
, arg1
);
149 if (TCG_TARGET_HAS_ext16u_i32
) {
150 tcg_gen_op2_i32(INDEX_op_ext16u_i32
, ret
, arg1
);
156 tcg_gen_and_i32(ret
, arg1
, tcg_constant_i32(arg2
));
159 void tcg_gen_ori_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
161 /* Some cases can be optimized here. */
163 tcg_gen_movi_i32(ret
, -1);
164 } else if (arg2
== 0) {
165 tcg_gen_mov_i32(ret
, arg1
);
167 tcg_gen_or_i32(ret
, arg1
, tcg_constant_i32(arg2
));
171 void tcg_gen_xori_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
173 /* Some cases can be optimized here. */
175 tcg_gen_mov_i32(ret
, arg1
);
176 } else if (arg2
== -1 && TCG_TARGET_HAS_not_i32
) {
177 /* Don't recurse with tcg_gen_not_i32. */
178 tcg_gen_op2_i32(INDEX_op_not_i32
, ret
, arg1
);
180 tcg_gen_xor_i32(ret
, arg1
, tcg_constant_i32(arg2
));
184 void tcg_gen_shli_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
186 tcg_debug_assert(arg2
>= 0 && arg2
< 32);
188 tcg_gen_mov_i32(ret
, arg1
);
190 tcg_gen_shl_i32(ret
, arg1
, tcg_constant_i32(arg2
));
194 void tcg_gen_shri_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
196 tcg_debug_assert(arg2
>= 0 && arg2
< 32);
198 tcg_gen_mov_i32(ret
, arg1
);
200 tcg_gen_shr_i32(ret
, arg1
, tcg_constant_i32(arg2
));
204 void tcg_gen_sari_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
206 tcg_debug_assert(arg2
>= 0 && arg2
< 32);
208 tcg_gen_mov_i32(ret
, arg1
);
210 tcg_gen_sar_i32(ret
, arg1
, tcg_constant_i32(arg2
));
214 void tcg_gen_brcond_i32(TCGCond cond
, TCGv_i32 arg1
, TCGv_i32 arg2
, TCGLabel
*l
)
216 if (cond
== TCG_COND_ALWAYS
) {
218 } else if (cond
!= TCG_COND_NEVER
) {
220 tcg_gen_op4ii_i32(INDEX_op_brcond_i32
, arg1
, arg2
, cond
, label_arg(l
));
224 void tcg_gen_brcondi_i32(TCGCond cond
, TCGv_i32 arg1
, int32_t arg2
, TCGLabel
*l
)
226 if (cond
== TCG_COND_ALWAYS
) {
228 } else if (cond
!= TCG_COND_NEVER
) {
229 tcg_gen_brcond_i32(cond
, arg1
, tcg_constant_i32(arg2
), l
);
233 void tcg_gen_setcond_i32(TCGCond cond
, TCGv_i32 ret
,
234 TCGv_i32 arg1
, TCGv_i32 arg2
)
236 if (cond
== TCG_COND_ALWAYS
) {
237 tcg_gen_movi_i32(ret
, 1);
238 } else if (cond
== TCG_COND_NEVER
) {
239 tcg_gen_movi_i32(ret
, 0);
241 tcg_gen_op4i_i32(INDEX_op_setcond_i32
, ret
, arg1
, arg2
, cond
);
245 void tcg_gen_setcondi_i32(TCGCond cond
, TCGv_i32 ret
,
246 TCGv_i32 arg1
, int32_t arg2
)
248 tcg_gen_setcond_i32(cond
, ret
, arg1
, tcg_constant_i32(arg2
));
251 void tcg_gen_muli_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
254 tcg_gen_movi_i32(ret
, 0);
255 } else if (is_power_of_2(arg2
)) {
256 tcg_gen_shli_i32(ret
, arg1
, ctz32(arg2
));
258 tcg_gen_mul_i32(ret
, arg1
, tcg_constant_i32(arg2
));
262 void tcg_gen_div_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
264 if (TCG_TARGET_HAS_div_i32
) {
265 tcg_gen_op3_i32(INDEX_op_div_i32
, ret
, arg1
, arg2
);
266 } else if (TCG_TARGET_HAS_div2_i32
) {
267 TCGv_i32 t0
= tcg_temp_new_i32();
268 tcg_gen_sari_i32(t0
, arg1
, 31);
269 tcg_gen_op5_i32(INDEX_op_div2_i32
, ret
, t0
, arg1
, t0
, arg2
);
270 tcg_temp_free_i32(t0
);
272 gen_helper_div_i32(ret
, arg1
, arg2
);
276 void tcg_gen_rem_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
278 if (TCG_TARGET_HAS_rem_i32
) {
279 tcg_gen_op3_i32(INDEX_op_rem_i32
, ret
, arg1
, arg2
);
280 } else if (TCG_TARGET_HAS_div_i32
) {
281 TCGv_i32 t0
= tcg_temp_new_i32();
282 tcg_gen_op3_i32(INDEX_op_div_i32
, t0
, arg1
, arg2
);
283 tcg_gen_mul_i32(t0
, t0
, arg2
);
284 tcg_gen_sub_i32(ret
, arg1
, t0
);
285 tcg_temp_free_i32(t0
);
286 } else if (TCG_TARGET_HAS_div2_i32
) {
287 TCGv_i32 t0
= tcg_temp_new_i32();
288 tcg_gen_sari_i32(t0
, arg1
, 31);
289 tcg_gen_op5_i32(INDEX_op_div2_i32
, t0
, ret
, arg1
, t0
, arg2
);
290 tcg_temp_free_i32(t0
);
292 gen_helper_rem_i32(ret
, arg1
, arg2
);
296 void tcg_gen_divu_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
298 if (TCG_TARGET_HAS_div_i32
) {
299 tcg_gen_op3_i32(INDEX_op_divu_i32
, ret
, arg1
, arg2
);
300 } else if (TCG_TARGET_HAS_div2_i32
) {
301 TCGv_i32 t0
= tcg_temp_new_i32();
302 tcg_gen_movi_i32(t0
, 0);
303 tcg_gen_op5_i32(INDEX_op_divu2_i32
, ret
, t0
, arg1
, t0
, arg2
);
304 tcg_temp_free_i32(t0
);
306 gen_helper_divu_i32(ret
, arg1
, arg2
);
310 void tcg_gen_remu_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
312 if (TCG_TARGET_HAS_rem_i32
) {
313 tcg_gen_op3_i32(INDEX_op_remu_i32
, ret
, arg1
, arg2
);
314 } else if (TCG_TARGET_HAS_div_i32
) {
315 TCGv_i32 t0
= tcg_temp_new_i32();
316 tcg_gen_op3_i32(INDEX_op_divu_i32
, t0
, arg1
, arg2
);
317 tcg_gen_mul_i32(t0
, t0
, arg2
);
318 tcg_gen_sub_i32(ret
, arg1
, t0
);
319 tcg_temp_free_i32(t0
);
320 } else if (TCG_TARGET_HAS_div2_i32
) {
321 TCGv_i32 t0
= tcg_temp_new_i32();
322 tcg_gen_movi_i32(t0
, 0);
323 tcg_gen_op5_i32(INDEX_op_divu2_i32
, t0
, ret
, arg1
, t0
, arg2
);
324 tcg_temp_free_i32(t0
);
326 gen_helper_remu_i32(ret
, arg1
, arg2
);
330 void tcg_gen_andc_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
332 if (TCG_TARGET_HAS_andc_i32
) {
333 tcg_gen_op3_i32(INDEX_op_andc_i32
, ret
, arg1
, arg2
);
335 TCGv_i32 t0
= tcg_temp_new_i32();
336 tcg_gen_not_i32(t0
, arg2
);
337 tcg_gen_and_i32(ret
, arg1
, t0
);
338 tcg_temp_free_i32(t0
);
342 void tcg_gen_eqv_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
344 if (TCG_TARGET_HAS_eqv_i32
) {
345 tcg_gen_op3_i32(INDEX_op_eqv_i32
, ret
, arg1
, arg2
);
347 tcg_gen_xor_i32(ret
, arg1
, arg2
);
348 tcg_gen_not_i32(ret
, ret
);
352 void tcg_gen_nand_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
354 if (TCG_TARGET_HAS_nand_i32
) {
355 tcg_gen_op3_i32(INDEX_op_nand_i32
, ret
, arg1
, arg2
);
357 tcg_gen_and_i32(ret
, arg1
, arg2
);
358 tcg_gen_not_i32(ret
, ret
);
362 void tcg_gen_nor_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
364 if (TCG_TARGET_HAS_nor_i32
) {
365 tcg_gen_op3_i32(INDEX_op_nor_i32
, ret
, arg1
, arg2
);
367 tcg_gen_or_i32(ret
, arg1
, arg2
);
368 tcg_gen_not_i32(ret
, ret
);
372 void tcg_gen_orc_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
374 if (TCG_TARGET_HAS_orc_i32
) {
375 tcg_gen_op3_i32(INDEX_op_orc_i32
, ret
, arg1
, arg2
);
377 TCGv_i32 t0
= tcg_temp_new_i32();
378 tcg_gen_not_i32(t0
, arg2
);
379 tcg_gen_or_i32(ret
, arg1
, t0
);
380 tcg_temp_free_i32(t0
);
384 void tcg_gen_clz_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
386 if (TCG_TARGET_HAS_clz_i32
) {
387 tcg_gen_op3_i32(INDEX_op_clz_i32
, ret
, arg1
, arg2
);
388 } else if (TCG_TARGET_HAS_clz_i64
) {
389 TCGv_i64 t1
= tcg_temp_new_i64();
390 TCGv_i64 t2
= tcg_temp_new_i64();
391 tcg_gen_extu_i32_i64(t1
, arg1
);
392 tcg_gen_extu_i32_i64(t2
, arg2
);
393 tcg_gen_addi_i64(t2
, t2
, 32);
394 tcg_gen_clz_i64(t1
, t1
, t2
);
395 tcg_gen_extrl_i64_i32(ret
, t1
);
396 tcg_temp_free_i64(t1
);
397 tcg_temp_free_i64(t2
);
398 tcg_gen_subi_i32(ret
, ret
, 32);
400 gen_helper_clz_i32(ret
, arg1
, arg2
);
404 void tcg_gen_clzi_i32(TCGv_i32 ret
, TCGv_i32 arg1
, uint32_t arg2
)
406 tcg_gen_clz_i32(ret
, arg1
, tcg_constant_i32(arg2
));
409 void tcg_gen_ctz_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
411 if (TCG_TARGET_HAS_ctz_i32
) {
412 tcg_gen_op3_i32(INDEX_op_ctz_i32
, ret
, arg1
, arg2
);
413 } else if (TCG_TARGET_HAS_ctz_i64
) {
414 TCGv_i64 t1
= tcg_temp_new_i64();
415 TCGv_i64 t2
= tcg_temp_new_i64();
416 tcg_gen_extu_i32_i64(t1
, arg1
);
417 tcg_gen_extu_i32_i64(t2
, arg2
);
418 tcg_gen_ctz_i64(t1
, t1
, t2
);
419 tcg_gen_extrl_i64_i32(ret
, t1
);
420 tcg_temp_free_i64(t1
);
421 tcg_temp_free_i64(t2
);
422 } else if (TCG_TARGET_HAS_ctpop_i32
423 || TCG_TARGET_HAS_ctpop_i64
424 || TCG_TARGET_HAS_clz_i32
425 || TCG_TARGET_HAS_clz_i64
) {
426 TCGv_i32 z
, t
= tcg_temp_new_i32();
428 if (TCG_TARGET_HAS_ctpop_i32
|| TCG_TARGET_HAS_ctpop_i64
) {
429 tcg_gen_subi_i32(t
, arg1
, 1);
430 tcg_gen_andc_i32(t
, t
, arg1
);
431 tcg_gen_ctpop_i32(t
, t
);
433 /* Since all non-x86 hosts have clz(0) == 32, don't fight it. */
434 tcg_gen_neg_i32(t
, arg1
);
435 tcg_gen_and_i32(t
, t
, arg1
);
436 tcg_gen_clzi_i32(t
, t
, 32);
437 tcg_gen_xori_i32(t
, t
, 31);
439 z
= tcg_constant_i32(0);
440 tcg_gen_movcond_i32(TCG_COND_EQ
, ret
, arg1
, z
, arg2
, t
);
441 tcg_temp_free_i32(t
);
443 gen_helper_ctz_i32(ret
, arg1
, arg2
);
447 void tcg_gen_ctzi_i32(TCGv_i32 ret
, TCGv_i32 arg1
, uint32_t arg2
)
449 if (!TCG_TARGET_HAS_ctz_i32
&& TCG_TARGET_HAS_ctpop_i32
&& arg2
== 32) {
450 /* This equivalence has the advantage of not requiring a fixup. */
451 TCGv_i32 t
= tcg_temp_new_i32();
452 tcg_gen_subi_i32(t
, arg1
, 1);
453 tcg_gen_andc_i32(t
, t
, arg1
);
454 tcg_gen_ctpop_i32(ret
, t
);
455 tcg_temp_free_i32(t
);
457 tcg_gen_ctz_i32(ret
, arg1
, tcg_constant_i32(arg2
));
461 void tcg_gen_clrsb_i32(TCGv_i32 ret
, TCGv_i32 arg
)
463 if (TCG_TARGET_HAS_clz_i32
) {
464 TCGv_i32 t
= tcg_temp_new_i32();
465 tcg_gen_sari_i32(t
, arg
, 31);
466 tcg_gen_xor_i32(t
, t
, arg
);
467 tcg_gen_clzi_i32(t
, t
, 32);
468 tcg_gen_subi_i32(ret
, t
, 1);
469 tcg_temp_free_i32(t
);
471 gen_helper_clrsb_i32(ret
, arg
);
475 void tcg_gen_ctpop_i32(TCGv_i32 ret
, TCGv_i32 arg1
)
477 if (TCG_TARGET_HAS_ctpop_i32
) {
478 tcg_gen_op2_i32(INDEX_op_ctpop_i32
, ret
, arg1
);
479 } else if (TCG_TARGET_HAS_ctpop_i64
) {
480 TCGv_i64 t
= tcg_temp_new_i64();
481 tcg_gen_extu_i32_i64(t
, arg1
);
482 tcg_gen_ctpop_i64(t
, t
);
483 tcg_gen_extrl_i64_i32(ret
, t
);
484 tcg_temp_free_i64(t
);
486 gen_helper_ctpop_i32(ret
, arg1
);
490 void tcg_gen_rotl_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
492 if (TCG_TARGET_HAS_rot_i32
) {
493 tcg_gen_op3_i32(INDEX_op_rotl_i32
, ret
, arg1
, arg2
);
497 t0
= tcg_temp_new_i32();
498 t1
= tcg_temp_new_i32();
499 tcg_gen_shl_i32(t0
, arg1
, arg2
);
500 tcg_gen_subfi_i32(t1
, 32, arg2
);
501 tcg_gen_shr_i32(t1
, arg1
, t1
);
502 tcg_gen_or_i32(ret
, t0
, t1
);
503 tcg_temp_free_i32(t0
);
504 tcg_temp_free_i32(t1
);
508 void tcg_gen_rotli_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
510 tcg_debug_assert(arg2
>= 0 && arg2
< 32);
511 /* some cases can be optimized here */
513 tcg_gen_mov_i32(ret
, arg1
);
514 } else if (TCG_TARGET_HAS_rot_i32
) {
515 tcg_gen_rotl_i32(ret
, arg1
, tcg_constant_i32(arg2
));
518 t0
= tcg_temp_new_i32();
519 t1
= tcg_temp_new_i32();
520 tcg_gen_shli_i32(t0
, arg1
, arg2
);
521 tcg_gen_shri_i32(t1
, arg1
, 32 - arg2
);
522 tcg_gen_or_i32(ret
, t0
, t1
);
523 tcg_temp_free_i32(t0
);
524 tcg_temp_free_i32(t1
);
528 void tcg_gen_rotr_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
)
530 if (TCG_TARGET_HAS_rot_i32
) {
531 tcg_gen_op3_i32(INDEX_op_rotr_i32
, ret
, arg1
, arg2
);
535 t0
= tcg_temp_new_i32();
536 t1
= tcg_temp_new_i32();
537 tcg_gen_shr_i32(t0
, arg1
, arg2
);
538 tcg_gen_subfi_i32(t1
, 32, arg2
);
539 tcg_gen_shl_i32(t1
, arg1
, t1
);
540 tcg_gen_or_i32(ret
, t0
, t1
);
541 tcg_temp_free_i32(t0
);
542 tcg_temp_free_i32(t1
);
546 void tcg_gen_rotri_i32(TCGv_i32 ret
, TCGv_i32 arg1
, int32_t arg2
)
548 tcg_debug_assert(arg2
>= 0 && arg2
< 32);
549 /* some cases can be optimized here */
551 tcg_gen_mov_i32(ret
, arg1
);
553 tcg_gen_rotli_i32(ret
, arg1
, 32 - arg2
);
557 void tcg_gen_deposit_i32(TCGv_i32 ret
, TCGv_i32 arg1
, TCGv_i32 arg2
,
558 unsigned int ofs
, unsigned int len
)
563 tcg_debug_assert(ofs
< 32);
564 tcg_debug_assert(len
> 0);
565 tcg_debug_assert(len
<= 32);
566 tcg_debug_assert(ofs
+ len
<= 32);
569 tcg_gen_mov_i32(ret
, arg2
);
572 if (TCG_TARGET_HAS_deposit_i32
&& TCG_TARGET_deposit_i32_valid(ofs
, len
)) {
573 tcg_gen_op5ii_i32(INDEX_op_deposit_i32
, ret
, arg1
, arg2
, ofs
, len
);
577 t1
= tcg_temp_new_i32();
579 if (TCG_TARGET_HAS_extract2_i32
) {
580 if (ofs
+ len
== 32) {
581 tcg_gen_shli_i32(t1
, arg1
, len
);
582 tcg_gen_extract2_i32(ret
, t1
, arg2
, len
);
586 tcg_gen_extract2_i32(ret
, arg1
, arg2
, len
);
587 tcg_gen_rotli_i32(ret
, ret
, len
);
592 mask
= (1u << len
) - 1;
593 if (ofs
+ len
< 32) {
594 tcg_gen_andi_i32(t1
, arg2
, mask
);
595 tcg_gen_shli_i32(t1
, t1
, ofs
);
597 tcg_gen_shli_i32(t1
, arg2
, ofs
);
599 tcg_gen_andi_i32(ret
, arg1
, ~(mask
<< ofs
));
600 tcg_gen_or_i32(ret
, ret
, t1
);
602 tcg_temp_free_i32(t1
);
605 void tcg_gen_deposit_z_i32(TCGv_i32 ret
, TCGv_i32 arg
,
606 unsigned int ofs
, unsigned int len
)
608 tcg_debug_assert(ofs
< 32);
609 tcg_debug_assert(len
> 0);
610 tcg_debug_assert(len
<= 32);
611 tcg_debug_assert(ofs
+ len
<= 32);
613 if (ofs
+ len
== 32) {
614 tcg_gen_shli_i32(ret
, arg
, ofs
);
615 } else if (ofs
== 0) {
616 tcg_gen_andi_i32(ret
, arg
, (1u << len
) - 1);
617 } else if (TCG_TARGET_HAS_deposit_i32
618 && TCG_TARGET_deposit_i32_valid(ofs
, len
)) {
619 TCGv_i32 zero
= tcg_constant_i32(0);
620 tcg_gen_op5ii_i32(INDEX_op_deposit_i32
, ret
, zero
, arg
, ofs
, len
);
622 /* To help two-operand hosts we prefer to zero-extend first,
623 which allows ARG to stay live. */
626 if (TCG_TARGET_HAS_ext16u_i32
) {
627 tcg_gen_ext16u_i32(ret
, arg
);
628 tcg_gen_shli_i32(ret
, ret
, ofs
);
633 if (TCG_TARGET_HAS_ext8u_i32
) {
634 tcg_gen_ext8u_i32(ret
, arg
);
635 tcg_gen_shli_i32(ret
, ret
, ofs
);
640 /* Otherwise prefer zero-extension over AND for code size. */
643 if (TCG_TARGET_HAS_ext16u_i32
) {
644 tcg_gen_shli_i32(ret
, arg
, ofs
);
645 tcg_gen_ext16u_i32(ret
, ret
);
650 if (TCG_TARGET_HAS_ext8u_i32
) {
651 tcg_gen_shli_i32(ret
, arg
, ofs
);
652 tcg_gen_ext8u_i32(ret
, ret
);
657 tcg_gen_andi_i32(ret
, arg
, (1u << len
) - 1);
658 tcg_gen_shli_i32(ret
, ret
, ofs
);
662 void tcg_gen_extract_i32(TCGv_i32 ret
, TCGv_i32 arg
,
663 unsigned int ofs
, unsigned int len
)
665 tcg_debug_assert(ofs
< 32);
666 tcg_debug_assert(len
> 0);
667 tcg_debug_assert(len
<= 32);
668 tcg_debug_assert(ofs
+ len
<= 32);
670 /* Canonicalize certain special cases, even if extract is supported. */
671 if (ofs
+ len
== 32) {
672 tcg_gen_shri_i32(ret
, arg
, 32 - len
);
676 tcg_gen_andi_i32(ret
, arg
, (1u << len
) - 1);
680 if (TCG_TARGET_HAS_extract_i32
681 && TCG_TARGET_extract_i32_valid(ofs
, len
)) {
682 tcg_gen_op4ii_i32(INDEX_op_extract_i32
, ret
, arg
, ofs
, len
);
686 /* Assume that zero-extension, if available, is cheaper than a shift. */
689 if (TCG_TARGET_HAS_ext16u_i32
) {
690 tcg_gen_ext16u_i32(ret
, arg
);
691 tcg_gen_shri_i32(ret
, ret
, ofs
);
696 if (TCG_TARGET_HAS_ext8u_i32
) {
697 tcg_gen_ext8u_i32(ret
, arg
);
698 tcg_gen_shri_i32(ret
, ret
, ofs
);
704 /* ??? Ideally we'd know what values are available for immediate AND.
705 Assume that 8 bits are available, plus the special case of 16,
706 so that we get ext8u, ext16u. */
708 case 1 ... 8: case 16:
709 tcg_gen_shri_i32(ret
, arg
, ofs
);
710 tcg_gen_andi_i32(ret
, ret
, (1u << len
) - 1);
713 tcg_gen_shli_i32(ret
, arg
, 32 - len
- ofs
);
714 tcg_gen_shri_i32(ret
, ret
, 32 - len
);
719 void tcg_gen_sextract_i32(TCGv_i32 ret
, TCGv_i32 arg
,
720 unsigned int ofs
, unsigned int len
)
722 tcg_debug_assert(ofs
< 32);
723 tcg_debug_assert(len
> 0);
724 tcg_debug_assert(len
<= 32);
725 tcg_debug_assert(ofs
+ len
<= 32);
727 /* Canonicalize certain special cases, even if extract is supported. */
728 if (ofs
+ len
== 32) {
729 tcg_gen_sari_i32(ret
, arg
, 32 - len
);
735 tcg_gen_ext16s_i32(ret
, arg
);
738 tcg_gen_ext8s_i32(ret
, arg
);
743 if (TCG_TARGET_HAS_sextract_i32
744 && TCG_TARGET_extract_i32_valid(ofs
, len
)) {
745 tcg_gen_op4ii_i32(INDEX_op_sextract_i32
, ret
, arg
, ofs
, len
);
749 /* Assume that sign-extension, if available, is cheaper than a shift. */
752 if (TCG_TARGET_HAS_ext16s_i32
) {
753 tcg_gen_ext16s_i32(ret
, arg
);
754 tcg_gen_sari_i32(ret
, ret
, ofs
);
759 if (TCG_TARGET_HAS_ext8s_i32
) {
760 tcg_gen_ext8s_i32(ret
, arg
);
761 tcg_gen_sari_i32(ret
, ret
, ofs
);
768 if (TCG_TARGET_HAS_ext16s_i32
) {
769 tcg_gen_shri_i32(ret
, arg
, ofs
);
770 tcg_gen_ext16s_i32(ret
, ret
);
775 if (TCG_TARGET_HAS_ext8s_i32
) {
776 tcg_gen_shri_i32(ret
, arg
, ofs
);
777 tcg_gen_ext8s_i32(ret
, ret
);
783 tcg_gen_shli_i32(ret
, arg
, 32 - len
- ofs
);
784 tcg_gen_sari_i32(ret
, ret
, 32 - len
);
788 * Extract 32-bits from a 64-bit input, ah:al, starting from ofs.
789 * Unlike tcg_gen_extract_i32 above, len is fixed at 32.
791 void tcg_gen_extract2_i32(TCGv_i32 ret
, TCGv_i32 al
, TCGv_i32 ah
,
794 tcg_debug_assert(ofs
<= 32);
796 tcg_gen_mov_i32(ret
, al
);
797 } else if (ofs
== 32) {
798 tcg_gen_mov_i32(ret
, ah
);
799 } else if (al
== ah
) {
800 tcg_gen_rotri_i32(ret
, al
, ofs
);
801 } else if (TCG_TARGET_HAS_extract2_i32
) {
802 tcg_gen_op4i_i32(INDEX_op_extract2_i32
, ret
, al
, ah
, ofs
);
804 TCGv_i32 t0
= tcg_temp_new_i32();
805 tcg_gen_shri_i32(t0
, al
, ofs
);
806 tcg_gen_deposit_i32(ret
, t0
, ah
, 32 - ofs
, ofs
);
807 tcg_temp_free_i32(t0
);
811 void tcg_gen_movcond_i32(TCGCond cond
, TCGv_i32 ret
, TCGv_i32 c1
,
812 TCGv_i32 c2
, TCGv_i32 v1
, TCGv_i32 v2
)
814 if (cond
== TCG_COND_ALWAYS
) {
815 tcg_gen_mov_i32(ret
, v1
);
816 } else if (cond
== TCG_COND_NEVER
) {
817 tcg_gen_mov_i32(ret
, v2
);
818 } else if (TCG_TARGET_HAS_movcond_i32
) {
819 tcg_gen_op6i_i32(INDEX_op_movcond_i32
, ret
, c1
, c2
, v1
, v2
, cond
);
821 TCGv_i32 t0
= tcg_temp_new_i32();
822 TCGv_i32 t1
= tcg_temp_new_i32();
823 tcg_gen_setcond_i32(cond
, t0
, c1
, c2
);
824 tcg_gen_neg_i32(t0
, t0
);
825 tcg_gen_and_i32(t1
, v1
, t0
);
826 tcg_gen_andc_i32(ret
, v2
, t0
);
827 tcg_gen_or_i32(ret
, ret
, t1
);
828 tcg_temp_free_i32(t0
);
829 tcg_temp_free_i32(t1
);
833 void tcg_gen_add2_i32(TCGv_i32 rl
, TCGv_i32 rh
, TCGv_i32 al
,
834 TCGv_i32 ah
, TCGv_i32 bl
, TCGv_i32 bh
)
836 if (TCG_TARGET_HAS_add2_i32
) {
837 tcg_gen_op6_i32(INDEX_op_add2_i32
, rl
, rh
, al
, ah
, bl
, bh
);
839 TCGv_i64 t0
= tcg_temp_new_i64();
840 TCGv_i64 t1
= tcg_temp_new_i64();
841 tcg_gen_concat_i32_i64(t0
, al
, ah
);
842 tcg_gen_concat_i32_i64(t1
, bl
, bh
);
843 tcg_gen_add_i64(t0
, t0
, t1
);
844 tcg_gen_extr_i64_i32(rl
, rh
, t0
);
845 tcg_temp_free_i64(t0
);
846 tcg_temp_free_i64(t1
);
850 void tcg_gen_sub2_i32(TCGv_i32 rl
, TCGv_i32 rh
, TCGv_i32 al
,
851 TCGv_i32 ah
, TCGv_i32 bl
, TCGv_i32 bh
)
853 if (TCG_TARGET_HAS_sub2_i32
) {
854 tcg_gen_op6_i32(INDEX_op_sub2_i32
, rl
, rh
, al
, ah
, bl
, bh
);
856 TCGv_i64 t0
= tcg_temp_new_i64();
857 TCGv_i64 t1
= tcg_temp_new_i64();
858 tcg_gen_concat_i32_i64(t0
, al
, ah
);
859 tcg_gen_concat_i32_i64(t1
, bl
, bh
);
860 tcg_gen_sub_i64(t0
, t0
, t1
);
861 tcg_gen_extr_i64_i32(rl
, rh
, t0
);
862 tcg_temp_free_i64(t0
);
863 tcg_temp_free_i64(t1
);
867 void tcg_gen_mulu2_i32(TCGv_i32 rl
, TCGv_i32 rh
, TCGv_i32 arg1
, TCGv_i32 arg2
)
869 if (TCG_TARGET_HAS_mulu2_i32
) {
870 tcg_gen_op4_i32(INDEX_op_mulu2_i32
, rl
, rh
, arg1
, arg2
);
871 } else if (TCG_TARGET_HAS_muluh_i32
) {
872 TCGv_i32 t
= tcg_temp_new_i32();
873 tcg_gen_op3_i32(INDEX_op_mul_i32
, t
, arg1
, arg2
);
874 tcg_gen_op3_i32(INDEX_op_muluh_i32
, rh
, arg1
, arg2
);
875 tcg_gen_mov_i32(rl
, t
);
876 tcg_temp_free_i32(t
);
877 } else if (TCG_TARGET_REG_BITS
== 64) {
878 TCGv_i64 t0
= tcg_temp_new_i64();
879 TCGv_i64 t1
= tcg_temp_new_i64();
880 tcg_gen_extu_i32_i64(t0
, arg1
);
881 tcg_gen_extu_i32_i64(t1
, arg2
);
882 tcg_gen_mul_i64(t0
, t0
, t1
);
883 tcg_gen_extr_i64_i32(rl
, rh
, t0
);
884 tcg_temp_free_i64(t0
);
885 tcg_temp_free_i64(t1
);
887 qemu_build_not_reached();
891 void tcg_gen_muls2_i32(TCGv_i32 rl
, TCGv_i32 rh
, TCGv_i32 arg1
, TCGv_i32 arg2
)
893 if (TCG_TARGET_HAS_muls2_i32
) {
894 tcg_gen_op4_i32(INDEX_op_muls2_i32
, rl
, rh
, arg1
, arg2
);
895 } else if (TCG_TARGET_HAS_mulsh_i32
) {
896 TCGv_i32 t
= tcg_temp_new_i32();
897 tcg_gen_op3_i32(INDEX_op_mul_i32
, t
, arg1
, arg2
);
898 tcg_gen_op3_i32(INDEX_op_mulsh_i32
, rh
, arg1
, arg2
);
899 tcg_gen_mov_i32(rl
, t
);
900 tcg_temp_free_i32(t
);
901 } else if (TCG_TARGET_REG_BITS
== 32) {
902 TCGv_i32 t0
= tcg_temp_new_i32();
903 TCGv_i32 t1
= tcg_temp_new_i32();
904 TCGv_i32 t2
= tcg_temp_new_i32();
905 TCGv_i32 t3
= tcg_temp_new_i32();
906 tcg_gen_mulu2_i32(t0
, t1
, arg1
, arg2
);
907 /* Adjust for negative inputs. */
908 tcg_gen_sari_i32(t2
, arg1
, 31);
909 tcg_gen_sari_i32(t3
, arg2
, 31);
910 tcg_gen_and_i32(t2
, t2
, arg2
);
911 tcg_gen_and_i32(t3
, t3
, arg1
);
912 tcg_gen_sub_i32(rh
, t1
, t2
);
913 tcg_gen_sub_i32(rh
, rh
, t3
);
914 tcg_gen_mov_i32(rl
, t0
);
915 tcg_temp_free_i32(t0
);
916 tcg_temp_free_i32(t1
);
917 tcg_temp_free_i32(t2
);
918 tcg_temp_free_i32(t3
);
920 TCGv_i64 t0
= tcg_temp_new_i64();
921 TCGv_i64 t1
= tcg_temp_new_i64();
922 tcg_gen_ext_i32_i64(t0
, arg1
);
923 tcg_gen_ext_i32_i64(t1
, arg2
);
924 tcg_gen_mul_i64(t0
, t0
, t1
);
925 tcg_gen_extr_i64_i32(rl
, rh
, t0
);
926 tcg_temp_free_i64(t0
);
927 tcg_temp_free_i64(t1
);
931 void tcg_gen_mulsu2_i32(TCGv_i32 rl
, TCGv_i32 rh
, TCGv_i32 arg1
, TCGv_i32 arg2
)
933 if (TCG_TARGET_REG_BITS
== 32) {
934 TCGv_i32 t0
= tcg_temp_new_i32();
935 TCGv_i32 t1
= tcg_temp_new_i32();
936 TCGv_i32 t2
= tcg_temp_new_i32();
937 tcg_gen_mulu2_i32(t0
, t1
, arg1
, arg2
);
938 /* Adjust for negative input for the signed arg1. */
939 tcg_gen_sari_i32(t2
, arg1
, 31);
940 tcg_gen_and_i32(t2
, t2
, arg2
);
941 tcg_gen_sub_i32(rh
, t1
, t2
);
942 tcg_gen_mov_i32(rl
, t0
);
943 tcg_temp_free_i32(t0
);
944 tcg_temp_free_i32(t1
);
945 tcg_temp_free_i32(t2
);
947 TCGv_i64 t0
= tcg_temp_new_i64();
948 TCGv_i64 t1
= tcg_temp_new_i64();
949 tcg_gen_ext_i32_i64(t0
, arg1
);
950 tcg_gen_extu_i32_i64(t1
, arg2
);
951 tcg_gen_mul_i64(t0
, t0
, t1
);
952 tcg_gen_extr_i64_i32(rl
, rh
, t0
);
953 tcg_temp_free_i64(t0
);
954 tcg_temp_free_i64(t1
);
958 void tcg_gen_ext8s_i32(TCGv_i32 ret
, TCGv_i32 arg
)
960 if (TCG_TARGET_HAS_ext8s_i32
) {
961 tcg_gen_op2_i32(INDEX_op_ext8s_i32
, ret
, arg
);
963 tcg_gen_shli_i32(ret
, arg
, 24);
964 tcg_gen_sari_i32(ret
, ret
, 24);
968 void tcg_gen_ext16s_i32(TCGv_i32 ret
, TCGv_i32 arg
)
970 if (TCG_TARGET_HAS_ext16s_i32
) {
971 tcg_gen_op2_i32(INDEX_op_ext16s_i32
, ret
, arg
);
973 tcg_gen_shli_i32(ret
, arg
, 16);
974 tcg_gen_sari_i32(ret
, ret
, 16);
978 void tcg_gen_ext8u_i32(TCGv_i32 ret
, TCGv_i32 arg
)
980 if (TCG_TARGET_HAS_ext8u_i32
) {
981 tcg_gen_op2_i32(INDEX_op_ext8u_i32
, ret
, arg
);
983 tcg_gen_andi_i32(ret
, arg
, 0xffu
);
987 void tcg_gen_ext16u_i32(TCGv_i32 ret
, TCGv_i32 arg
)
989 if (TCG_TARGET_HAS_ext16u_i32
) {
990 tcg_gen_op2_i32(INDEX_op_ext16u_i32
, ret
, arg
);
992 tcg_gen_andi_i32(ret
, arg
, 0xffffu
);
996 void tcg_gen_bswap16_i32(TCGv_i32 ret
, TCGv_i32 arg
, int flags
)
998 /* Only one extension flag may be present. */
999 tcg_debug_assert(!(flags
& TCG_BSWAP_OS
) || !(flags
& TCG_BSWAP_OZ
));
1001 if (TCG_TARGET_HAS_bswap16_i32
) {
1002 tcg_gen_op3i_i32(INDEX_op_bswap16_i32
, ret
, arg
, flags
);
1004 TCGv_i32 t0
= tcg_temp_new_i32();
1005 TCGv_i32 t1
= tcg_temp_new_i32();
1007 tcg_gen_shri_i32(t0
, arg
, 8);
1008 if (!(flags
& TCG_BSWAP_IZ
)) {
1009 tcg_gen_ext8u_i32(t0
, t0
);
1012 if (flags
& TCG_BSWAP_OS
) {
1013 tcg_gen_shli_i32(t1
, arg
, 24);
1014 tcg_gen_sari_i32(t1
, t1
, 16);
1015 } else if (flags
& TCG_BSWAP_OZ
) {
1016 tcg_gen_ext8u_i32(t1
, arg
);
1017 tcg_gen_shli_i32(t1
, t1
, 8);
1019 tcg_gen_shli_i32(t1
, arg
, 8);
1022 tcg_gen_or_i32(ret
, t0
, t1
);
1023 tcg_temp_free_i32(t0
);
1024 tcg_temp_free_i32(t1
);
1028 void tcg_gen_bswap32_i32(TCGv_i32 ret
, TCGv_i32 arg
)
1030 if (TCG_TARGET_HAS_bswap32_i32
) {
1031 tcg_gen_op3i_i32(INDEX_op_bswap32_i32
, ret
, arg
, 0);
1033 TCGv_i32 t0
= tcg_temp_new_i32();
1034 TCGv_i32 t1
= tcg_temp_new_i32();
1035 TCGv_i32 t2
= tcg_constant_i32(0x00ff00ff);
1038 tcg_gen_shri_i32(t0
, arg
, 8); /* t0 = .abc */
1039 tcg_gen_and_i32(t1
, arg
, t2
); /* t1 = .b.d */
1040 tcg_gen_and_i32(t0
, t0
, t2
); /* t0 = .a.c */
1041 tcg_gen_shli_i32(t1
, t1
, 8); /* t1 = b.d. */
1042 tcg_gen_or_i32(ret
, t0
, t1
); /* ret = badc */
1044 tcg_gen_shri_i32(t0
, ret
, 16); /* t0 = ..ba */
1045 tcg_gen_shli_i32(t1
, ret
, 16); /* t1 = dc.. */
1046 tcg_gen_or_i32(ret
, t0
, t1
); /* ret = dcba */
1048 tcg_temp_free_i32(t0
);
1049 tcg_temp_free_i32(t1
);
1053 void tcg_gen_hswap_i32(TCGv_i32 ret
, TCGv_i32 arg
)
1055 /* Swapping 2 16-bit elements is a rotate. */
1056 tcg_gen_rotli_i32(ret
, arg
, 16);
1059 void tcg_gen_smin_i32(TCGv_i32 ret
, TCGv_i32 a
, TCGv_i32 b
)
1061 tcg_gen_movcond_i32(TCG_COND_LT
, ret
, a
, b
, a
, b
);
1064 void tcg_gen_umin_i32(TCGv_i32 ret
, TCGv_i32 a
, TCGv_i32 b
)
1066 tcg_gen_movcond_i32(TCG_COND_LTU
, ret
, a
, b
, a
, b
);
1069 void tcg_gen_smax_i32(TCGv_i32 ret
, TCGv_i32 a
, TCGv_i32 b
)
1071 tcg_gen_movcond_i32(TCG_COND_LT
, ret
, a
, b
, b
, a
);
1074 void tcg_gen_umax_i32(TCGv_i32 ret
, TCGv_i32 a
, TCGv_i32 b
)
1076 tcg_gen_movcond_i32(TCG_COND_LTU
, ret
, a
, b
, b
, a
);
1079 void tcg_gen_abs_i32(TCGv_i32 ret
, TCGv_i32 a
)
1081 TCGv_i32 t
= tcg_temp_new_i32();
1083 tcg_gen_sari_i32(t
, a
, 31);
1084 tcg_gen_xor_i32(ret
, a
, t
);
1085 tcg_gen_sub_i32(ret
, ret
, t
);
1086 tcg_temp_free_i32(t
);
1091 #if TCG_TARGET_REG_BITS == 32
1092 /* These are all inline for TCG_TARGET_REG_BITS == 64. */
1094 void tcg_gen_discard_i64(TCGv_i64 arg
)
1096 tcg_gen_discard_i32(TCGV_LOW(arg
));
1097 tcg_gen_discard_i32(TCGV_HIGH(arg
));
1100 void tcg_gen_mov_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1102 TCGTemp
*ts
= tcgv_i64_temp(arg
);
1104 /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
1105 if (ts
->kind
== TEMP_CONST
) {
1106 tcg_gen_movi_i64(ret
, ts
->val
);
1108 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1109 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg
));
1113 void tcg_gen_movi_i64(TCGv_i64 ret
, int64_t arg
)
1115 tcg_gen_movi_i32(TCGV_LOW(ret
), arg
);
1116 tcg_gen_movi_i32(TCGV_HIGH(ret
), arg
>> 32);
1119 void tcg_gen_ld8u_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1121 tcg_gen_ld8u_i32(TCGV_LOW(ret
), arg2
, offset
);
1122 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1125 void tcg_gen_ld8s_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1127 tcg_gen_ld8s_i32(TCGV_LOW(ret
), arg2
, offset
);
1128 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1131 void tcg_gen_ld16u_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1133 tcg_gen_ld16u_i32(TCGV_LOW(ret
), arg2
, offset
);
1134 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1137 void tcg_gen_ld16s_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1139 tcg_gen_ld16s_i32(TCGV_LOW(ret
), arg2
, offset
);
1140 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1143 void tcg_gen_ld32u_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1145 tcg_gen_ld_i32(TCGV_LOW(ret
), arg2
, offset
);
1146 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1149 void tcg_gen_ld32s_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1151 tcg_gen_ld_i32(TCGV_LOW(ret
), arg2
, offset
);
1152 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1155 void tcg_gen_ld_i64(TCGv_i64 ret
, TCGv_ptr arg2
, tcg_target_long offset
)
1157 /* Since arg2 and ret have different types,
1158 they cannot be the same temporary */
1160 tcg_gen_ld_i32(TCGV_HIGH(ret
), arg2
, offset
);
1161 tcg_gen_ld_i32(TCGV_LOW(ret
), arg2
, offset
+ 4);
1163 tcg_gen_ld_i32(TCGV_LOW(ret
), arg2
, offset
);
1164 tcg_gen_ld_i32(TCGV_HIGH(ret
), arg2
, offset
+ 4);
1168 void tcg_gen_st8_i64(TCGv_i64 arg1
, TCGv_ptr arg2
, tcg_target_long offset
)
1170 tcg_gen_st8_i32(TCGV_LOW(arg1
), arg2
, offset
);
1173 void tcg_gen_st16_i64(TCGv_i64 arg1
, TCGv_ptr arg2
, tcg_target_long offset
)
1175 tcg_gen_st16_i32(TCGV_LOW(arg1
), arg2
, offset
);
1178 void tcg_gen_st32_i64(TCGv_i64 arg1
, TCGv_ptr arg2
, tcg_target_long offset
)
1180 tcg_gen_st_i32(TCGV_LOW(arg1
), arg2
, offset
);
1183 void tcg_gen_st_i64(TCGv_i64 arg1
, TCGv_ptr arg2
, tcg_target_long offset
)
1186 tcg_gen_st_i32(TCGV_HIGH(arg1
), arg2
, offset
);
1187 tcg_gen_st_i32(TCGV_LOW(arg1
), arg2
, offset
+ 4);
1189 tcg_gen_st_i32(TCGV_LOW(arg1
), arg2
, offset
);
1190 tcg_gen_st_i32(TCGV_HIGH(arg1
), arg2
, offset
+ 4);
1194 void tcg_gen_add_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1196 tcg_gen_add2_i32(TCGV_LOW(ret
), TCGV_HIGH(ret
), TCGV_LOW(arg1
),
1197 TCGV_HIGH(arg1
), TCGV_LOW(arg2
), TCGV_HIGH(arg2
));
1200 void tcg_gen_sub_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1202 tcg_gen_sub2_i32(TCGV_LOW(ret
), TCGV_HIGH(ret
), TCGV_LOW(arg1
),
1203 TCGV_HIGH(arg1
), TCGV_LOW(arg2
), TCGV_HIGH(arg2
));
1206 void tcg_gen_and_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1208 tcg_gen_and_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1209 tcg_gen_and_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1212 void tcg_gen_or_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1214 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1215 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1218 void tcg_gen_xor_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1220 tcg_gen_xor_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1221 tcg_gen_xor_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1224 void tcg_gen_shl_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1226 gen_helper_shl_i64(ret
, arg1
, arg2
);
1229 void tcg_gen_shr_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1231 gen_helper_shr_i64(ret
, arg1
, arg2
);
1234 void tcg_gen_sar_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1236 gen_helper_sar_i64(ret
, arg1
, arg2
);
1239 void tcg_gen_mul_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1244 t0
= tcg_temp_new_i64();
1245 t1
= tcg_temp_new_i32();
1247 tcg_gen_mulu2_i32(TCGV_LOW(t0
), TCGV_HIGH(t0
),
1248 TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1250 tcg_gen_mul_i32(t1
, TCGV_LOW(arg1
), TCGV_HIGH(arg2
));
1251 tcg_gen_add_i32(TCGV_HIGH(t0
), TCGV_HIGH(t0
), t1
);
1252 tcg_gen_mul_i32(t1
, TCGV_HIGH(arg1
), TCGV_LOW(arg2
));
1253 tcg_gen_add_i32(TCGV_HIGH(t0
), TCGV_HIGH(t0
), t1
);
1255 tcg_gen_mov_i64(ret
, t0
);
1256 tcg_temp_free_i64(t0
);
1257 tcg_temp_free_i32(t1
);
1262 void tcg_gen_movi_i64(TCGv_i64 ret
, int64_t arg
)
1264 tcg_gen_mov_i64(ret
, tcg_constant_i64(arg
));
1267 #endif /* TCG_TARGET_REG_SIZE == 32 */
1269 void tcg_gen_addi_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1271 /* some cases can be optimized here */
1273 tcg_gen_mov_i64(ret
, arg1
);
1274 } else if (TCG_TARGET_REG_BITS
== 64) {
1275 tcg_gen_add_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1277 tcg_gen_add2_i32(TCGV_LOW(ret
), TCGV_HIGH(ret
),
1278 TCGV_LOW(arg1
), TCGV_HIGH(arg1
),
1279 tcg_constant_i32(arg2
), tcg_constant_i32(arg2
>> 32));
1283 void tcg_gen_subfi_i64(TCGv_i64 ret
, int64_t arg1
, TCGv_i64 arg2
)
1285 if (arg1
== 0 && TCG_TARGET_HAS_neg_i64
) {
1286 /* Don't recurse with tcg_gen_neg_i64. */
1287 tcg_gen_op2_i64(INDEX_op_neg_i64
, ret
, arg2
);
1288 } else if (TCG_TARGET_REG_BITS
== 64) {
1289 tcg_gen_sub_i64(ret
, tcg_constant_i64(arg1
), arg2
);
1291 tcg_gen_sub2_i32(TCGV_LOW(ret
), TCGV_HIGH(ret
),
1292 tcg_constant_i32(arg1
), tcg_constant_i32(arg1
>> 32),
1293 TCGV_LOW(arg2
), TCGV_HIGH(arg2
));
1297 void tcg_gen_subi_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1299 /* some cases can be optimized here */
1301 tcg_gen_mov_i64(ret
, arg1
);
1302 } else if (TCG_TARGET_REG_BITS
== 64) {
1303 tcg_gen_sub_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1305 tcg_gen_sub2_i32(TCGV_LOW(ret
), TCGV_HIGH(ret
),
1306 TCGV_LOW(arg1
), TCGV_HIGH(arg1
),
1307 tcg_constant_i32(arg2
), tcg_constant_i32(arg2
>> 32));
1311 void tcg_gen_andi_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1313 if (TCG_TARGET_REG_BITS
== 32) {
1314 tcg_gen_andi_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), arg2
);
1315 tcg_gen_andi_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), arg2
>> 32);
1319 /* Some cases can be optimized here. */
1322 tcg_gen_movi_i64(ret
, 0);
1325 tcg_gen_mov_i64(ret
, arg1
);
1328 /* Don't recurse with tcg_gen_ext8u_i64. */
1329 if (TCG_TARGET_HAS_ext8u_i64
) {
1330 tcg_gen_op2_i64(INDEX_op_ext8u_i64
, ret
, arg1
);
1335 if (TCG_TARGET_HAS_ext16u_i64
) {
1336 tcg_gen_op2_i64(INDEX_op_ext16u_i64
, ret
, arg1
);
1341 if (TCG_TARGET_HAS_ext32u_i64
) {
1342 tcg_gen_op2_i64(INDEX_op_ext32u_i64
, ret
, arg1
);
1348 tcg_gen_and_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1351 void tcg_gen_ori_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1353 if (TCG_TARGET_REG_BITS
== 32) {
1354 tcg_gen_ori_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), arg2
);
1355 tcg_gen_ori_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), arg2
>> 32);
1358 /* Some cases can be optimized here. */
1360 tcg_gen_movi_i64(ret
, -1);
1361 } else if (arg2
== 0) {
1362 tcg_gen_mov_i64(ret
, arg1
);
1364 tcg_gen_or_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1368 void tcg_gen_xori_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1370 if (TCG_TARGET_REG_BITS
== 32) {
1371 tcg_gen_xori_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), arg2
);
1372 tcg_gen_xori_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), arg2
>> 32);
1375 /* Some cases can be optimized here. */
1377 tcg_gen_mov_i64(ret
, arg1
);
1378 } else if (arg2
== -1 && TCG_TARGET_HAS_not_i64
) {
1379 /* Don't recurse with tcg_gen_not_i64. */
1380 tcg_gen_op2_i64(INDEX_op_not_i64
, ret
, arg1
);
1382 tcg_gen_xor_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1386 static inline void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
1387 unsigned c
, bool right
, bool arith
)
1389 tcg_debug_assert(c
< 64);
1391 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
1392 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
1393 } else if (c
>= 32) {
1397 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
1398 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
1400 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
1401 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1404 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
1405 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
1408 if (TCG_TARGET_HAS_extract2_i32
) {
1409 tcg_gen_extract2_i32(TCGV_LOW(ret
),
1410 TCGV_LOW(arg1
), TCGV_HIGH(arg1
), c
);
1412 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
1413 tcg_gen_deposit_i32(TCGV_LOW(ret
), TCGV_LOW(ret
),
1414 TCGV_HIGH(arg1
), 32 - c
, c
);
1417 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
1419 tcg_gen_shri_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
1422 if (TCG_TARGET_HAS_extract2_i32
) {
1423 tcg_gen_extract2_i32(TCGV_HIGH(ret
),
1424 TCGV_LOW(arg1
), TCGV_HIGH(arg1
), 32 - c
);
1426 TCGv_i32 t0
= tcg_temp_new_i32();
1427 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
1428 tcg_gen_deposit_i32(TCGV_HIGH(ret
), t0
,
1429 TCGV_HIGH(arg1
), c
, 32 - c
);
1430 tcg_temp_free_i32(t0
);
1432 tcg_gen_shli_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
1436 void tcg_gen_shli_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1438 tcg_debug_assert(arg2
>= 0 && arg2
< 64);
1439 if (TCG_TARGET_REG_BITS
== 32) {
1440 tcg_gen_shifti_i64(ret
, arg1
, arg2
, 0, 0);
1441 } else if (arg2
== 0) {
1442 tcg_gen_mov_i64(ret
, arg1
);
1444 tcg_gen_shl_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1448 void tcg_gen_shri_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1450 tcg_debug_assert(arg2
>= 0 && arg2
< 64);
1451 if (TCG_TARGET_REG_BITS
== 32) {
1452 tcg_gen_shifti_i64(ret
, arg1
, arg2
, 1, 0);
1453 } else if (arg2
== 0) {
1454 tcg_gen_mov_i64(ret
, arg1
);
1456 tcg_gen_shr_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1460 void tcg_gen_sari_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1462 tcg_debug_assert(arg2
>= 0 && arg2
< 64);
1463 if (TCG_TARGET_REG_BITS
== 32) {
1464 tcg_gen_shifti_i64(ret
, arg1
, arg2
, 1, 1);
1465 } else if (arg2
== 0) {
1466 tcg_gen_mov_i64(ret
, arg1
);
1468 tcg_gen_sar_i64(ret
, arg1
, tcg_constant_i64(arg2
));
1472 void tcg_gen_brcond_i64(TCGCond cond
, TCGv_i64 arg1
, TCGv_i64 arg2
, TCGLabel
*l
)
1474 if (cond
== TCG_COND_ALWAYS
) {
1476 } else if (cond
!= TCG_COND_NEVER
) {
1478 if (TCG_TARGET_REG_BITS
== 32) {
1479 tcg_gen_op6ii_i32(INDEX_op_brcond2_i32
, TCGV_LOW(arg1
),
1480 TCGV_HIGH(arg1
), TCGV_LOW(arg2
),
1481 TCGV_HIGH(arg2
), cond
, label_arg(l
));
1483 tcg_gen_op4ii_i64(INDEX_op_brcond_i64
, arg1
, arg2
, cond
,
1489 void tcg_gen_brcondi_i64(TCGCond cond
, TCGv_i64 arg1
, int64_t arg2
, TCGLabel
*l
)
1491 if (TCG_TARGET_REG_BITS
== 64) {
1492 tcg_gen_brcond_i64(cond
, arg1
, tcg_constant_i64(arg2
), l
);
1493 } else if (cond
== TCG_COND_ALWAYS
) {
1495 } else if (cond
!= TCG_COND_NEVER
) {
1497 tcg_gen_op6ii_i32(INDEX_op_brcond2_i32
,
1498 TCGV_LOW(arg1
), TCGV_HIGH(arg1
),
1499 tcg_constant_i32(arg2
),
1500 tcg_constant_i32(arg2
>> 32),
1501 cond
, label_arg(l
));
1505 void tcg_gen_setcond_i64(TCGCond cond
, TCGv_i64 ret
,
1506 TCGv_i64 arg1
, TCGv_i64 arg2
)
1508 if (cond
== TCG_COND_ALWAYS
) {
1509 tcg_gen_movi_i64(ret
, 1);
1510 } else if (cond
== TCG_COND_NEVER
) {
1511 tcg_gen_movi_i64(ret
, 0);
1513 if (TCG_TARGET_REG_BITS
== 32) {
1514 tcg_gen_op6i_i32(INDEX_op_setcond2_i32
, TCGV_LOW(ret
),
1515 TCGV_LOW(arg1
), TCGV_HIGH(arg1
),
1516 TCGV_LOW(arg2
), TCGV_HIGH(arg2
), cond
);
1517 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1519 tcg_gen_op4i_i64(INDEX_op_setcond_i64
, ret
, arg1
, arg2
, cond
);
1524 void tcg_gen_setcondi_i64(TCGCond cond
, TCGv_i64 ret
,
1525 TCGv_i64 arg1
, int64_t arg2
)
1527 if (TCG_TARGET_REG_BITS
== 64) {
1528 tcg_gen_setcond_i64(cond
, ret
, arg1
, tcg_constant_i64(arg2
));
1529 } else if (cond
== TCG_COND_ALWAYS
) {
1530 tcg_gen_movi_i64(ret
, 1);
1531 } else if (cond
== TCG_COND_NEVER
) {
1532 tcg_gen_movi_i64(ret
, 0);
1534 tcg_gen_op6i_i32(INDEX_op_setcond2_i32
, TCGV_LOW(ret
),
1535 TCGV_LOW(arg1
), TCGV_HIGH(arg1
),
1536 tcg_constant_i32(arg2
),
1537 tcg_constant_i32(arg2
>> 32), cond
);
1538 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1542 void tcg_gen_muli_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
1545 tcg_gen_movi_i64(ret
, 0);
1546 } else if (is_power_of_2(arg2
)) {
1547 tcg_gen_shli_i64(ret
, arg1
, ctz64(arg2
));
1549 TCGv_i64 t0
= tcg_const_i64(arg2
);
1550 tcg_gen_mul_i64(ret
, arg1
, t0
);
1551 tcg_temp_free_i64(t0
);
1555 void tcg_gen_div_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1557 if (TCG_TARGET_HAS_div_i64
) {
1558 tcg_gen_op3_i64(INDEX_op_div_i64
, ret
, arg1
, arg2
);
1559 } else if (TCG_TARGET_HAS_div2_i64
) {
1560 TCGv_i64 t0
= tcg_temp_new_i64();
1561 tcg_gen_sari_i64(t0
, arg1
, 63);
1562 tcg_gen_op5_i64(INDEX_op_div2_i64
, ret
, t0
, arg1
, t0
, arg2
);
1563 tcg_temp_free_i64(t0
);
1565 gen_helper_div_i64(ret
, arg1
, arg2
);
1569 void tcg_gen_rem_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1571 if (TCG_TARGET_HAS_rem_i64
) {
1572 tcg_gen_op3_i64(INDEX_op_rem_i64
, ret
, arg1
, arg2
);
1573 } else if (TCG_TARGET_HAS_div_i64
) {
1574 TCGv_i64 t0
= tcg_temp_new_i64();
1575 tcg_gen_op3_i64(INDEX_op_div_i64
, t0
, arg1
, arg2
);
1576 tcg_gen_mul_i64(t0
, t0
, arg2
);
1577 tcg_gen_sub_i64(ret
, arg1
, t0
);
1578 tcg_temp_free_i64(t0
);
1579 } else if (TCG_TARGET_HAS_div2_i64
) {
1580 TCGv_i64 t0
= tcg_temp_new_i64();
1581 tcg_gen_sari_i64(t0
, arg1
, 63);
1582 tcg_gen_op5_i64(INDEX_op_div2_i64
, t0
, ret
, arg1
, t0
, arg2
);
1583 tcg_temp_free_i64(t0
);
1585 gen_helper_rem_i64(ret
, arg1
, arg2
);
1589 void tcg_gen_divu_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1591 if (TCG_TARGET_HAS_div_i64
) {
1592 tcg_gen_op3_i64(INDEX_op_divu_i64
, ret
, arg1
, arg2
);
1593 } else if (TCG_TARGET_HAS_div2_i64
) {
1594 TCGv_i64 t0
= tcg_temp_new_i64();
1595 tcg_gen_movi_i64(t0
, 0);
1596 tcg_gen_op5_i64(INDEX_op_divu2_i64
, ret
, t0
, arg1
, t0
, arg2
);
1597 tcg_temp_free_i64(t0
);
1599 gen_helper_divu_i64(ret
, arg1
, arg2
);
1603 void tcg_gen_remu_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1605 if (TCG_TARGET_HAS_rem_i64
) {
1606 tcg_gen_op3_i64(INDEX_op_remu_i64
, ret
, arg1
, arg2
);
1607 } else if (TCG_TARGET_HAS_div_i64
) {
1608 TCGv_i64 t0
= tcg_temp_new_i64();
1609 tcg_gen_op3_i64(INDEX_op_divu_i64
, t0
, arg1
, arg2
);
1610 tcg_gen_mul_i64(t0
, t0
, arg2
);
1611 tcg_gen_sub_i64(ret
, arg1
, t0
);
1612 tcg_temp_free_i64(t0
);
1613 } else if (TCG_TARGET_HAS_div2_i64
) {
1614 TCGv_i64 t0
= tcg_temp_new_i64();
1615 tcg_gen_movi_i64(t0
, 0);
1616 tcg_gen_op5_i64(INDEX_op_divu2_i64
, t0
, ret
, arg1
, t0
, arg2
);
1617 tcg_temp_free_i64(t0
);
1619 gen_helper_remu_i64(ret
, arg1
, arg2
);
1623 void tcg_gen_ext8s_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1625 if (TCG_TARGET_REG_BITS
== 32) {
1626 tcg_gen_ext8s_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1627 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1628 } else if (TCG_TARGET_HAS_ext8s_i64
) {
1629 tcg_gen_op2_i64(INDEX_op_ext8s_i64
, ret
, arg
);
1631 tcg_gen_shli_i64(ret
, arg
, 56);
1632 tcg_gen_sari_i64(ret
, ret
, 56);
1636 void tcg_gen_ext16s_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1638 if (TCG_TARGET_REG_BITS
== 32) {
1639 tcg_gen_ext16s_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1640 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1641 } else if (TCG_TARGET_HAS_ext16s_i64
) {
1642 tcg_gen_op2_i64(INDEX_op_ext16s_i64
, ret
, arg
);
1644 tcg_gen_shli_i64(ret
, arg
, 48);
1645 tcg_gen_sari_i64(ret
, ret
, 48);
1649 void tcg_gen_ext32s_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1651 if (TCG_TARGET_REG_BITS
== 32) {
1652 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1653 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1654 } else if (TCG_TARGET_HAS_ext32s_i64
) {
1655 tcg_gen_op2_i64(INDEX_op_ext32s_i64
, ret
, arg
);
1657 tcg_gen_shli_i64(ret
, arg
, 32);
1658 tcg_gen_sari_i64(ret
, ret
, 32);
1662 void tcg_gen_ext8u_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1664 if (TCG_TARGET_REG_BITS
== 32) {
1665 tcg_gen_ext8u_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1666 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1667 } else if (TCG_TARGET_HAS_ext8u_i64
) {
1668 tcg_gen_op2_i64(INDEX_op_ext8u_i64
, ret
, arg
);
1670 tcg_gen_andi_i64(ret
, arg
, 0xffu
);
1674 void tcg_gen_ext16u_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1676 if (TCG_TARGET_REG_BITS
== 32) {
1677 tcg_gen_ext16u_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1678 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1679 } else if (TCG_TARGET_HAS_ext16u_i64
) {
1680 tcg_gen_op2_i64(INDEX_op_ext16u_i64
, ret
, arg
);
1682 tcg_gen_andi_i64(ret
, arg
, 0xffffu
);
1686 void tcg_gen_ext32u_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1688 if (TCG_TARGET_REG_BITS
== 32) {
1689 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1690 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1691 } else if (TCG_TARGET_HAS_ext32u_i64
) {
1692 tcg_gen_op2_i64(INDEX_op_ext32u_i64
, ret
, arg
);
1694 tcg_gen_andi_i64(ret
, arg
, 0xffffffffu
);
1698 void tcg_gen_bswap16_i64(TCGv_i64 ret
, TCGv_i64 arg
, int flags
)
1700 /* Only one extension flag may be present. */
1701 tcg_debug_assert(!(flags
& TCG_BSWAP_OS
) || !(flags
& TCG_BSWAP_OZ
));
1703 if (TCG_TARGET_REG_BITS
== 32) {
1704 tcg_gen_bswap16_i32(TCGV_LOW(ret
), TCGV_LOW(arg
), flags
);
1705 if (flags
& TCG_BSWAP_OS
) {
1706 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1708 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1710 } else if (TCG_TARGET_HAS_bswap16_i64
) {
1711 tcg_gen_op3i_i64(INDEX_op_bswap16_i64
, ret
, arg
, flags
);
1713 TCGv_i64 t0
= tcg_temp_new_i64();
1714 TCGv_i64 t1
= tcg_temp_new_i64();
1716 tcg_gen_shri_i64(t0
, arg
, 8);
1717 if (!(flags
& TCG_BSWAP_IZ
)) {
1718 tcg_gen_ext8u_i64(t0
, t0
);
1721 if (flags
& TCG_BSWAP_OS
) {
1722 tcg_gen_shli_i64(t1
, arg
, 56);
1723 tcg_gen_sari_i64(t1
, t1
, 48);
1724 } else if (flags
& TCG_BSWAP_OZ
) {
1725 tcg_gen_ext8u_i64(t1
, arg
);
1726 tcg_gen_shli_i64(t1
, t1
, 8);
1728 tcg_gen_shli_i64(t1
, arg
, 8);
1731 tcg_gen_or_i64(ret
, t0
, t1
);
1732 tcg_temp_free_i64(t0
);
1733 tcg_temp_free_i64(t1
);
1737 void tcg_gen_bswap32_i64(TCGv_i64 ret
, TCGv_i64 arg
, int flags
)
1739 /* Only one extension flag may be present. */
1740 tcg_debug_assert(!(flags
& TCG_BSWAP_OS
) || !(flags
& TCG_BSWAP_OZ
));
1742 if (TCG_TARGET_REG_BITS
== 32) {
1743 tcg_gen_bswap32_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1744 if (flags
& TCG_BSWAP_OS
) {
1745 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
1747 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1749 } else if (TCG_TARGET_HAS_bswap32_i64
) {
1750 tcg_gen_op3i_i64(INDEX_op_bswap32_i64
, ret
, arg
, flags
);
1752 TCGv_i64 t0
= tcg_temp_new_i64();
1753 TCGv_i64 t1
= tcg_temp_new_i64();
1754 TCGv_i64 t2
= tcg_constant_i64(0x00ff00ff);
1756 /* arg = xxxxabcd */
1757 tcg_gen_shri_i64(t0
, arg
, 8); /* t0 = .xxxxabc */
1758 tcg_gen_and_i64(t1
, arg
, t2
); /* t1 = .....b.d */
1759 tcg_gen_and_i64(t0
, t0
, t2
); /* t0 = .....a.c */
1760 tcg_gen_shli_i64(t1
, t1
, 8); /* t1 = ....b.d. */
1761 tcg_gen_or_i64(ret
, t0
, t1
); /* ret = ....badc */
1763 tcg_gen_shli_i64(t1
, ret
, 48); /* t1 = dc...... */
1764 tcg_gen_shri_i64(t0
, ret
, 16); /* t0 = ......ba */
1765 if (flags
& TCG_BSWAP_OS
) {
1766 tcg_gen_sari_i64(t1
, t1
, 32); /* t1 = ssssdc.. */
1768 tcg_gen_shri_i64(t1
, t1
, 32); /* t1 = ....dc.. */
1770 tcg_gen_or_i64(ret
, t0
, t1
); /* ret = ssssdcba */
1772 tcg_temp_free_i64(t0
);
1773 tcg_temp_free_i64(t1
);
1777 void tcg_gen_bswap64_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1779 if (TCG_TARGET_REG_BITS
== 32) {
1781 t0
= tcg_temp_new_i32();
1782 t1
= tcg_temp_new_i32();
1784 tcg_gen_bswap32_i32(t0
, TCGV_LOW(arg
));
1785 tcg_gen_bswap32_i32(t1
, TCGV_HIGH(arg
));
1786 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
1787 tcg_gen_mov_i32(TCGV_HIGH(ret
), t0
);
1788 tcg_temp_free_i32(t0
);
1789 tcg_temp_free_i32(t1
);
1790 } else if (TCG_TARGET_HAS_bswap64_i64
) {
1791 tcg_gen_op3i_i64(INDEX_op_bswap64_i64
, ret
, arg
, 0);
1793 TCGv_i64 t0
= tcg_temp_new_i64();
1794 TCGv_i64 t1
= tcg_temp_new_i64();
1795 TCGv_i64 t2
= tcg_temp_new_i64();
1797 /* arg = abcdefgh */
1798 tcg_gen_movi_i64(t2
, 0x00ff00ff00ff00ffull
);
1799 tcg_gen_shri_i64(t0
, arg
, 8); /* t0 = .abcdefg */
1800 tcg_gen_and_i64(t1
, arg
, t2
); /* t1 = .b.d.f.h */
1801 tcg_gen_and_i64(t0
, t0
, t2
); /* t0 = .a.c.e.g */
1802 tcg_gen_shli_i64(t1
, t1
, 8); /* t1 = b.d.f.h. */
1803 tcg_gen_or_i64(ret
, t0
, t1
); /* ret = badcfehg */
1805 tcg_gen_movi_i64(t2
, 0x0000ffff0000ffffull
);
1806 tcg_gen_shri_i64(t0
, ret
, 16); /* t0 = ..badcfe */
1807 tcg_gen_and_i64(t1
, ret
, t2
); /* t1 = ..dc..hg */
1808 tcg_gen_and_i64(t0
, t0
, t2
); /* t0 = ..ba..fe */
1809 tcg_gen_shli_i64(t1
, t1
, 16); /* t1 = dc..hg.. */
1810 tcg_gen_or_i64(ret
, t0
, t1
); /* ret = dcbahgfe */
1812 tcg_gen_shri_i64(t0
, ret
, 32); /* t0 = ....dcba */
1813 tcg_gen_shli_i64(t1
, ret
, 32); /* t1 = hgfe.... */
1814 tcg_gen_or_i64(ret
, t0
, t1
); /* ret = hgfedcba */
1816 tcg_temp_free_i64(t0
);
1817 tcg_temp_free_i64(t1
);
1818 tcg_temp_free_i64(t2
);
1822 void tcg_gen_hswap_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1824 uint64_t m
= 0x0000ffff0000ffffull
;
1825 TCGv_i64 t0
= tcg_temp_new_i64();
1826 TCGv_i64 t1
= tcg_temp_new_i64();
1828 /* See include/qemu/bitops.h, hswap64. */
1829 tcg_gen_rotli_i64(t1
, arg
, 32);
1830 tcg_gen_andi_i64(t0
, t1
, m
);
1831 tcg_gen_shli_i64(t0
, t0
, 16);
1832 tcg_gen_shri_i64(t1
, t1
, 16);
1833 tcg_gen_andi_i64(t1
, t1
, m
);
1834 tcg_gen_or_i64(ret
, t0
, t1
);
1836 tcg_temp_free_i64(t0
);
1837 tcg_temp_free_i64(t1
);
1840 void tcg_gen_wswap_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1842 /* Swapping 2 32-bit elements is a rotate. */
1843 tcg_gen_rotli_i64(ret
, arg
, 32);
1846 void tcg_gen_not_i64(TCGv_i64 ret
, TCGv_i64 arg
)
1848 if (TCG_TARGET_REG_BITS
== 32) {
1849 tcg_gen_not_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
1850 tcg_gen_not_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg
));
1851 } else if (TCG_TARGET_HAS_not_i64
) {
1852 tcg_gen_op2_i64(INDEX_op_not_i64
, ret
, arg
);
1854 tcg_gen_xori_i64(ret
, arg
, -1);
1858 void tcg_gen_andc_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1860 if (TCG_TARGET_REG_BITS
== 32) {
1861 tcg_gen_andc_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1862 tcg_gen_andc_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1863 } else if (TCG_TARGET_HAS_andc_i64
) {
1864 tcg_gen_op3_i64(INDEX_op_andc_i64
, ret
, arg1
, arg2
);
1866 TCGv_i64 t0
= tcg_temp_new_i64();
1867 tcg_gen_not_i64(t0
, arg2
);
1868 tcg_gen_and_i64(ret
, arg1
, t0
);
1869 tcg_temp_free_i64(t0
);
1873 void tcg_gen_eqv_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1875 if (TCG_TARGET_REG_BITS
== 32) {
1876 tcg_gen_eqv_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1877 tcg_gen_eqv_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1878 } else if (TCG_TARGET_HAS_eqv_i64
) {
1879 tcg_gen_op3_i64(INDEX_op_eqv_i64
, ret
, arg1
, arg2
);
1881 tcg_gen_xor_i64(ret
, arg1
, arg2
);
1882 tcg_gen_not_i64(ret
, ret
);
1886 void tcg_gen_nand_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1888 if (TCG_TARGET_REG_BITS
== 32) {
1889 tcg_gen_nand_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1890 tcg_gen_nand_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1891 } else if (TCG_TARGET_HAS_nand_i64
) {
1892 tcg_gen_op3_i64(INDEX_op_nand_i64
, ret
, arg1
, arg2
);
1894 tcg_gen_and_i64(ret
, arg1
, arg2
);
1895 tcg_gen_not_i64(ret
, ret
);
1899 void tcg_gen_nor_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1901 if (TCG_TARGET_REG_BITS
== 32) {
1902 tcg_gen_nor_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1903 tcg_gen_nor_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1904 } else if (TCG_TARGET_HAS_nor_i64
) {
1905 tcg_gen_op3_i64(INDEX_op_nor_i64
, ret
, arg1
, arg2
);
1907 tcg_gen_or_i64(ret
, arg1
, arg2
);
1908 tcg_gen_not_i64(ret
, ret
);
1912 void tcg_gen_orc_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1914 if (TCG_TARGET_REG_BITS
== 32) {
1915 tcg_gen_orc_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), TCGV_LOW(arg2
));
1916 tcg_gen_orc_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), TCGV_HIGH(arg2
));
1917 } else if (TCG_TARGET_HAS_orc_i64
) {
1918 tcg_gen_op3_i64(INDEX_op_orc_i64
, ret
, arg1
, arg2
);
1920 TCGv_i64 t0
= tcg_temp_new_i64();
1921 tcg_gen_not_i64(t0
, arg2
);
1922 tcg_gen_or_i64(ret
, arg1
, t0
);
1923 tcg_temp_free_i64(t0
);
1927 void tcg_gen_clz_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1929 if (TCG_TARGET_HAS_clz_i64
) {
1930 tcg_gen_op3_i64(INDEX_op_clz_i64
, ret
, arg1
, arg2
);
1932 gen_helper_clz_i64(ret
, arg1
, arg2
);
1936 void tcg_gen_clzi_i64(TCGv_i64 ret
, TCGv_i64 arg1
, uint64_t arg2
)
1938 if (TCG_TARGET_REG_BITS
== 32
1939 && TCG_TARGET_HAS_clz_i32
1940 && arg2
<= 0xffffffffu
) {
1941 TCGv_i32 t
= tcg_temp_new_i32();
1942 tcg_gen_clzi_i32(t
, TCGV_LOW(arg1
), arg2
- 32);
1943 tcg_gen_addi_i32(t
, t
, 32);
1944 tcg_gen_clz_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), t
);
1945 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1946 tcg_temp_free_i32(t
);
1948 TCGv_i64 t0
= tcg_const_i64(arg2
);
1949 tcg_gen_clz_i64(ret
, arg1
, t0
);
1950 tcg_temp_free_i64(t0
);
1954 void tcg_gen_ctz_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
1956 if (TCG_TARGET_HAS_ctz_i64
) {
1957 tcg_gen_op3_i64(INDEX_op_ctz_i64
, ret
, arg1
, arg2
);
1958 } else if (TCG_TARGET_HAS_ctpop_i64
|| TCG_TARGET_HAS_clz_i64
) {
1959 TCGv_i64 z
, t
= tcg_temp_new_i64();
1961 if (TCG_TARGET_HAS_ctpop_i64
) {
1962 tcg_gen_subi_i64(t
, arg1
, 1);
1963 tcg_gen_andc_i64(t
, t
, arg1
);
1964 tcg_gen_ctpop_i64(t
, t
);
1966 /* Since all non-x86 hosts have clz(0) == 64, don't fight it. */
1967 tcg_gen_neg_i64(t
, arg1
);
1968 tcg_gen_and_i64(t
, t
, arg1
);
1969 tcg_gen_clzi_i64(t
, t
, 64);
1970 tcg_gen_xori_i64(t
, t
, 63);
1972 z
= tcg_constant_i64(0);
1973 tcg_gen_movcond_i64(TCG_COND_EQ
, ret
, arg1
, z
, arg2
, t
);
1974 tcg_temp_free_i64(t
);
1975 tcg_temp_free_i64(z
);
1977 gen_helper_ctz_i64(ret
, arg1
, arg2
);
1981 void tcg_gen_ctzi_i64(TCGv_i64 ret
, TCGv_i64 arg1
, uint64_t arg2
)
1983 if (TCG_TARGET_REG_BITS
== 32
1984 && TCG_TARGET_HAS_ctz_i32
1985 && arg2
<= 0xffffffffu
) {
1986 TCGv_i32 t32
= tcg_temp_new_i32();
1987 tcg_gen_ctzi_i32(t32
, TCGV_HIGH(arg1
), arg2
- 32);
1988 tcg_gen_addi_i32(t32
, t32
, 32);
1989 tcg_gen_ctz_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), t32
);
1990 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
1991 tcg_temp_free_i32(t32
);
1992 } else if (!TCG_TARGET_HAS_ctz_i64
1993 && TCG_TARGET_HAS_ctpop_i64
1995 /* This equivalence has the advantage of not requiring a fixup. */
1996 TCGv_i64 t
= tcg_temp_new_i64();
1997 tcg_gen_subi_i64(t
, arg1
, 1);
1998 tcg_gen_andc_i64(t
, t
, arg1
);
1999 tcg_gen_ctpop_i64(ret
, t
);
2000 tcg_temp_free_i64(t
);
2002 TCGv_i64 t0
= tcg_const_i64(arg2
);
2003 tcg_gen_ctz_i64(ret
, arg1
, t0
);
2004 tcg_temp_free_i64(t0
);
2008 void tcg_gen_clrsb_i64(TCGv_i64 ret
, TCGv_i64 arg
)
2010 if (TCG_TARGET_HAS_clz_i64
|| TCG_TARGET_HAS_clz_i32
) {
2011 TCGv_i64 t
= tcg_temp_new_i64();
2012 tcg_gen_sari_i64(t
, arg
, 63);
2013 tcg_gen_xor_i64(t
, t
, arg
);
2014 tcg_gen_clzi_i64(t
, t
, 64);
2015 tcg_gen_subi_i64(ret
, t
, 1);
2016 tcg_temp_free_i64(t
);
2018 gen_helper_clrsb_i64(ret
, arg
);
2022 void tcg_gen_ctpop_i64(TCGv_i64 ret
, TCGv_i64 arg1
)
2024 if (TCG_TARGET_HAS_ctpop_i64
) {
2025 tcg_gen_op2_i64(INDEX_op_ctpop_i64
, ret
, arg1
);
2026 } else if (TCG_TARGET_REG_BITS
== 32 && TCG_TARGET_HAS_ctpop_i32
) {
2027 tcg_gen_ctpop_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
2028 tcg_gen_ctpop_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
2029 tcg_gen_add_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), TCGV_HIGH(ret
));
2030 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
2032 gen_helper_ctpop_i64(ret
, arg1
);
2036 void tcg_gen_rotl_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
2038 if (TCG_TARGET_HAS_rot_i64
) {
2039 tcg_gen_op3_i64(INDEX_op_rotl_i64
, ret
, arg1
, arg2
);
2042 t0
= tcg_temp_new_i64();
2043 t1
= tcg_temp_new_i64();
2044 tcg_gen_shl_i64(t0
, arg1
, arg2
);
2045 tcg_gen_subfi_i64(t1
, 64, arg2
);
2046 tcg_gen_shr_i64(t1
, arg1
, t1
);
2047 tcg_gen_or_i64(ret
, t0
, t1
);
2048 tcg_temp_free_i64(t0
);
2049 tcg_temp_free_i64(t1
);
2053 void tcg_gen_rotli_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
2055 tcg_debug_assert(arg2
>= 0 && arg2
< 64);
2056 /* some cases can be optimized here */
2058 tcg_gen_mov_i64(ret
, arg1
);
2059 } else if (TCG_TARGET_HAS_rot_i64
) {
2060 tcg_gen_rotl_i64(ret
, arg1
, tcg_constant_i64(arg2
));
2063 t0
= tcg_temp_new_i64();
2064 t1
= tcg_temp_new_i64();
2065 tcg_gen_shli_i64(t0
, arg1
, arg2
);
2066 tcg_gen_shri_i64(t1
, arg1
, 64 - arg2
);
2067 tcg_gen_or_i64(ret
, t0
, t1
);
2068 tcg_temp_free_i64(t0
);
2069 tcg_temp_free_i64(t1
);
2073 void tcg_gen_rotr_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
)
2075 if (TCG_TARGET_HAS_rot_i64
) {
2076 tcg_gen_op3_i64(INDEX_op_rotr_i64
, ret
, arg1
, arg2
);
2079 t0
= tcg_temp_new_i64();
2080 t1
= tcg_temp_new_i64();
2081 tcg_gen_shr_i64(t0
, arg1
, arg2
);
2082 tcg_gen_subfi_i64(t1
, 64, arg2
);
2083 tcg_gen_shl_i64(t1
, arg1
, t1
);
2084 tcg_gen_or_i64(ret
, t0
, t1
);
2085 tcg_temp_free_i64(t0
);
2086 tcg_temp_free_i64(t1
);
2090 void tcg_gen_rotri_i64(TCGv_i64 ret
, TCGv_i64 arg1
, int64_t arg2
)
2092 tcg_debug_assert(arg2
>= 0 && arg2
< 64);
2093 /* some cases can be optimized here */
2095 tcg_gen_mov_i64(ret
, arg1
);
2097 tcg_gen_rotli_i64(ret
, arg1
, 64 - arg2
);
2101 void tcg_gen_deposit_i64(TCGv_i64 ret
, TCGv_i64 arg1
, TCGv_i64 arg2
,
2102 unsigned int ofs
, unsigned int len
)
2107 tcg_debug_assert(ofs
< 64);
2108 tcg_debug_assert(len
> 0);
2109 tcg_debug_assert(len
<= 64);
2110 tcg_debug_assert(ofs
+ len
<= 64);
2113 tcg_gen_mov_i64(ret
, arg2
);
2116 if (TCG_TARGET_HAS_deposit_i64
&& TCG_TARGET_deposit_i64_valid(ofs
, len
)) {
2117 tcg_gen_op5ii_i64(INDEX_op_deposit_i64
, ret
, arg1
, arg2
, ofs
, len
);
2121 if (TCG_TARGET_REG_BITS
== 32) {
2123 tcg_gen_deposit_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
),
2124 TCGV_LOW(arg2
), ofs
- 32, len
);
2125 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
2128 if (ofs
+ len
<= 32) {
2129 tcg_gen_deposit_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
),
2130 TCGV_LOW(arg2
), ofs
, len
);
2131 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
2136 t1
= tcg_temp_new_i64();
2138 if (TCG_TARGET_HAS_extract2_i64
) {
2139 if (ofs
+ len
== 64) {
2140 tcg_gen_shli_i64(t1
, arg1
, len
);
2141 tcg_gen_extract2_i64(ret
, t1
, arg2
, len
);
2145 tcg_gen_extract2_i64(ret
, arg1
, arg2
, len
);
2146 tcg_gen_rotli_i64(ret
, ret
, len
);
2151 mask
= (1ull << len
) - 1;
2152 if (ofs
+ len
< 64) {
2153 tcg_gen_andi_i64(t1
, arg2
, mask
);
2154 tcg_gen_shli_i64(t1
, t1
, ofs
);
2156 tcg_gen_shli_i64(t1
, arg2
, ofs
);
2158 tcg_gen_andi_i64(ret
, arg1
, ~(mask
<< ofs
));
2159 tcg_gen_or_i64(ret
, ret
, t1
);
2161 tcg_temp_free_i64(t1
);
2164 void tcg_gen_deposit_z_i64(TCGv_i64 ret
, TCGv_i64 arg
,
2165 unsigned int ofs
, unsigned int len
)
2167 tcg_debug_assert(ofs
< 64);
2168 tcg_debug_assert(len
> 0);
2169 tcg_debug_assert(len
<= 64);
2170 tcg_debug_assert(ofs
+ len
<= 64);
2172 if (ofs
+ len
== 64) {
2173 tcg_gen_shli_i64(ret
, arg
, ofs
);
2174 } else if (ofs
== 0) {
2175 tcg_gen_andi_i64(ret
, arg
, (1ull << len
) - 1);
2176 } else if (TCG_TARGET_HAS_deposit_i64
2177 && TCG_TARGET_deposit_i64_valid(ofs
, len
)) {
2178 TCGv_i64 zero
= tcg_constant_i64(0);
2179 tcg_gen_op5ii_i64(INDEX_op_deposit_i64
, ret
, zero
, arg
, ofs
, len
);
2181 if (TCG_TARGET_REG_BITS
== 32) {
2183 tcg_gen_deposit_z_i32(TCGV_HIGH(ret
), TCGV_LOW(arg
),
2185 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
2188 if (ofs
+ len
<= 32) {
2189 tcg_gen_deposit_z_i32(TCGV_LOW(ret
), TCGV_LOW(arg
), ofs
, len
);
2190 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
2194 /* To help two-operand hosts we prefer to zero-extend first,
2195 which allows ARG to stay live. */
2198 if (TCG_TARGET_HAS_ext32u_i64
) {
2199 tcg_gen_ext32u_i64(ret
, arg
);
2200 tcg_gen_shli_i64(ret
, ret
, ofs
);
2205 if (TCG_TARGET_HAS_ext16u_i64
) {
2206 tcg_gen_ext16u_i64(ret
, arg
);
2207 tcg_gen_shli_i64(ret
, ret
, ofs
);
2212 if (TCG_TARGET_HAS_ext8u_i64
) {
2213 tcg_gen_ext8u_i64(ret
, arg
);
2214 tcg_gen_shli_i64(ret
, ret
, ofs
);
2219 /* Otherwise prefer zero-extension over AND for code size. */
2220 switch (ofs
+ len
) {
2222 if (TCG_TARGET_HAS_ext32u_i64
) {
2223 tcg_gen_shli_i64(ret
, arg
, ofs
);
2224 tcg_gen_ext32u_i64(ret
, ret
);
2229 if (TCG_TARGET_HAS_ext16u_i64
) {
2230 tcg_gen_shli_i64(ret
, arg
, ofs
);
2231 tcg_gen_ext16u_i64(ret
, ret
);
2236 if (TCG_TARGET_HAS_ext8u_i64
) {
2237 tcg_gen_shli_i64(ret
, arg
, ofs
);
2238 tcg_gen_ext8u_i64(ret
, ret
);
2243 tcg_gen_andi_i64(ret
, arg
, (1ull << len
) - 1);
2244 tcg_gen_shli_i64(ret
, ret
, ofs
);
2248 void tcg_gen_extract_i64(TCGv_i64 ret
, TCGv_i64 arg
,
2249 unsigned int ofs
, unsigned int len
)
2251 tcg_debug_assert(ofs
< 64);
2252 tcg_debug_assert(len
> 0);
2253 tcg_debug_assert(len
<= 64);
2254 tcg_debug_assert(ofs
+ len
<= 64);
2256 /* Canonicalize certain special cases, even if extract is supported. */
2257 if (ofs
+ len
== 64) {
2258 tcg_gen_shri_i64(ret
, arg
, 64 - len
);
2262 tcg_gen_andi_i64(ret
, arg
, (1ull << len
) - 1);
2266 if (TCG_TARGET_REG_BITS
== 32) {
2267 /* Look for a 32-bit extract within one of the two words. */
2269 tcg_gen_extract_i32(TCGV_LOW(ret
), TCGV_HIGH(arg
), ofs
- 32, len
);
2270 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
2273 if (ofs
+ len
<= 32) {
2274 tcg_gen_extract_i32(TCGV_LOW(ret
), TCGV_LOW(arg
), ofs
, len
);
2275 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
2278 /* The field is split across two words. One double-word
2279 shift is better than two double-word shifts. */
2283 if (TCG_TARGET_HAS_extract_i64
2284 && TCG_TARGET_extract_i64_valid(ofs
, len
)) {
2285 tcg_gen_op4ii_i64(INDEX_op_extract_i64
, ret
, arg
, ofs
, len
);
2289 /* Assume that zero-extension, if available, is cheaper than a shift. */
2290 switch (ofs
+ len
) {
2292 if (TCG_TARGET_HAS_ext32u_i64
) {
2293 tcg_gen_ext32u_i64(ret
, arg
);
2294 tcg_gen_shri_i64(ret
, ret
, ofs
);
2299 if (TCG_TARGET_HAS_ext16u_i64
) {
2300 tcg_gen_ext16u_i64(ret
, arg
);
2301 tcg_gen_shri_i64(ret
, ret
, ofs
);
2306 if (TCG_TARGET_HAS_ext8u_i64
) {
2307 tcg_gen_ext8u_i64(ret
, arg
);
2308 tcg_gen_shri_i64(ret
, ret
, ofs
);
2314 /* ??? Ideally we'd know what values are available for immediate AND.
2315 Assume that 8 bits are available, plus the special cases of 16 and 32,
2316 so that we get ext8u, ext16u, and ext32u. */
2318 case 1 ... 8: case 16: case 32:
2320 tcg_gen_shri_i64(ret
, arg
, ofs
);
2321 tcg_gen_andi_i64(ret
, ret
, (1ull << len
) - 1);
2324 tcg_gen_shli_i64(ret
, arg
, 64 - len
- ofs
);
2325 tcg_gen_shri_i64(ret
, ret
, 64 - len
);
2330 void tcg_gen_sextract_i64(TCGv_i64 ret
, TCGv_i64 arg
,
2331 unsigned int ofs
, unsigned int len
)
2333 tcg_debug_assert(ofs
< 64);
2334 tcg_debug_assert(len
> 0);
2335 tcg_debug_assert(len
<= 64);
2336 tcg_debug_assert(ofs
+ len
<= 64);
2338 /* Canonicalize certain special cases, even if sextract is supported. */
2339 if (ofs
+ len
== 64) {
2340 tcg_gen_sari_i64(ret
, arg
, 64 - len
);
2346 tcg_gen_ext32s_i64(ret
, arg
);
2349 tcg_gen_ext16s_i64(ret
, arg
);
2352 tcg_gen_ext8s_i64(ret
, arg
);
2357 if (TCG_TARGET_REG_BITS
== 32) {
2358 /* Look for a 32-bit extract within one of the two words. */
2360 tcg_gen_sextract_i32(TCGV_LOW(ret
), TCGV_HIGH(arg
), ofs
- 32, len
);
2361 } else if (ofs
+ len
<= 32) {
2362 tcg_gen_sextract_i32(TCGV_LOW(ret
), TCGV_LOW(arg
), ofs
, len
);
2363 } else if (ofs
== 0) {
2364 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg
));
2365 tcg_gen_sextract_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg
), 0, len
- 32);
2367 } else if (len
> 32) {
2368 TCGv_i32 t
= tcg_temp_new_i32();
2369 /* Extract the bits for the high word normally. */
2370 tcg_gen_sextract_i32(t
, TCGV_HIGH(arg
), ofs
+ 32, len
- 32);
2371 /* Shift the field down for the low part. */
2372 tcg_gen_shri_i64(ret
, arg
, ofs
);
2373 /* Overwrite the shift into the high part. */
2374 tcg_gen_mov_i32(TCGV_HIGH(ret
), t
);
2375 tcg_temp_free_i32(t
);
2378 /* Shift the field down for the low part, such that the
2379 field sits at the MSB. */
2380 tcg_gen_shri_i64(ret
, arg
, ofs
+ len
- 32);
2381 /* Shift the field down from the MSB, sign extending. */
2382 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), 32 - len
);
2384 /* Sign-extend the field from 32 bits. */
2385 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
2389 if (TCG_TARGET_HAS_sextract_i64
2390 && TCG_TARGET_extract_i64_valid(ofs
, len
)) {
2391 tcg_gen_op4ii_i64(INDEX_op_sextract_i64
, ret
, arg
, ofs
, len
);
2395 /* Assume that sign-extension, if available, is cheaper than a shift. */
2396 switch (ofs
+ len
) {
2398 if (TCG_TARGET_HAS_ext32s_i64
) {
2399 tcg_gen_ext32s_i64(ret
, arg
);
2400 tcg_gen_sari_i64(ret
, ret
, ofs
);
2405 if (TCG_TARGET_HAS_ext16s_i64
) {
2406 tcg_gen_ext16s_i64(ret
, arg
);
2407 tcg_gen_sari_i64(ret
, ret
, ofs
);
2412 if (TCG_TARGET_HAS_ext8s_i64
) {
2413 tcg_gen_ext8s_i64(ret
, arg
);
2414 tcg_gen_sari_i64(ret
, ret
, ofs
);
2421 if (TCG_TARGET_HAS_ext32s_i64
) {
2422 tcg_gen_shri_i64(ret
, arg
, ofs
);
2423 tcg_gen_ext32s_i64(ret
, ret
);
2428 if (TCG_TARGET_HAS_ext16s_i64
) {
2429 tcg_gen_shri_i64(ret
, arg
, ofs
);
2430 tcg_gen_ext16s_i64(ret
, ret
);
2435 if (TCG_TARGET_HAS_ext8s_i64
) {
2436 tcg_gen_shri_i64(ret
, arg
, ofs
);
2437 tcg_gen_ext8s_i64(ret
, ret
);
2442 tcg_gen_shli_i64(ret
, arg
, 64 - len
- ofs
);
2443 tcg_gen_sari_i64(ret
, ret
, 64 - len
);
2447 * Extract 64 bits from a 128-bit input, ah:al, starting from ofs.
2448 * Unlike tcg_gen_extract_i64 above, len is fixed at 64.
2450 void tcg_gen_extract2_i64(TCGv_i64 ret
, TCGv_i64 al
, TCGv_i64 ah
,
2453 tcg_debug_assert(ofs
<= 64);
2455 tcg_gen_mov_i64(ret
, al
);
2456 } else if (ofs
== 64) {
2457 tcg_gen_mov_i64(ret
, ah
);
2458 } else if (al
== ah
) {
2459 tcg_gen_rotri_i64(ret
, al
, ofs
);
2460 } else if (TCG_TARGET_HAS_extract2_i64
) {
2461 tcg_gen_op4i_i64(INDEX_op_extract2_i64
, ret
, al
, ah
, ofs
);
2463 TCGv_i64 t0
= tcg_temp_new_i64();
2464 tcg_gen_shri_i64(t0
, al
, ofs
);
2465 tcg_gen_deposit_i64(ret
, t0
, ah
, 64 - ofs
, ofs
);
2466 tcg_temp_free_i64(t0
);
2470 void tcg_gen_movcond_i64(TCGCond cond
, TCGv_i64 ret
, TCGv_i64 c1
,
2471 TCGv_i64 c2
, TCGv_i64 v1
, TCGv_i64 v2
)
2473 if (cond
== TCG_COND_ALWAYS
) {
2474 tcg_gen_mov_i64(ret
, v1
);
2475 } else if (cond
== TCG_COND_NEVER
) {
2476 tcg_gen_mov_i64(ret
, v2
);
2477 } else if (TCG_TARGET_REG_BITS
== 32) {
2478 TCGv_i32 t0
= tcg_temp_new_i32();
2479 TCGv_i32 t1
= tcg_temp_new_i32();
2480 tcg_gen_op6i_i32(INDEX_op_setcond2_i32
, t0
,
2481 TCGV_LOW(c1
), TCGV_HIGH(c1
),
2482 TCGV_LOW(c2
), TCGV_HIGH(c2
), cond
);
2484 if (TCG_TARGET_HAS_movcond_i32
) {
2485 tcg_gen_movi_i32(t1
, 0);
2486 tcg_gen_movcond_i32(TCG_COND_NE
, TCGV_LOW(ret
), t0
, t1
,
2487 TCGV_LOW(v1
), TCGV_LOW(v2
));
2488 tcg_gen_movcond_i32(TCG_COND_NE
, TCGV_HIGH(ret
), t0
, t1
,
2489 TCGV_HIGH(v1
), TCGV_HIGH(v2
));
2491 tcg_gen_neg_i32(t0
, t0
);
2493 tcg_gen_and_i32(t1
, TCGV_LOW(v1
), t0
);
2494 tcg_gen_andc_i32(TCGV_LOW(ret
), TCGV_LOW(v2
), t0
);
2495 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t1
);
2497 tcg_gen_and_i32(t1
, TCGV_HIGH(v1
), t0
);
2498 tcg_gen_andc_i32(TCGV_HIGH(ret
), TCGV_HIGH(v2
), t0
);
2499 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t1
);
2501 tcg_temp_free_i32(t0
);
2502 tcg_temp_free_i32(t1
);
2503 } else if (TCG_TARGET_HAS_movcond_i64
) {
2504 tcg_gen_op6i_i64(INDEX_op_movcond_i64
, ret
, c1
, c2
, v1
, v2
, cond
);
2506 TCGv_i64 t0
= tcg_temp_new_i64();
2507 TCGv_i64 t1
= tcg_temp_new_i64();
2508 tcg_gen_setcond_i64(cond
, t0
, c1
, c2
);
2509 tcg_gen_neg_i64(t0
, t0
);
2510 tcg_gen_and_i64(t1
, v1
, t0
);
2511 tcg_gen_andc_i64(ret
, v2
, t0
);
2512 tcg_gen_or_i64(ret
, ret
, t1
);
2513 tcg_temp_free_i64(t0
);
2514 tcg_temp_free_i64(t1
);
2518 void tcg_gen_add2_i64(TCGv_i64 rl
, TCGv_i64 rh
, TCGv_i64 al
,
2519 TCGv_i64 ah
, TCGv_i64 bl
, TCGv_i64 bh
)
2521 if (TCG_TARGET_HAS_add2_i64
) {
2522 tcg_gen_op6_i64(INDEX_op_add2_i64
, rl
, rh
, al
, ah
, bl
, bh
);
2524 TCGv_i64 t0
= tcg_temp_new_i64();
2525 TCGv_i64 t1
= tcg_temp_new_i64();
2526 tcg_gen_add_i64(t0
, al
, bl
);
2527 tcg_gen_setcond_i64(TCG_COND_LTU
, t1
, t0
, al
);
2528 tcg_gen_add_i64(rh
, ah
, bh
);
2529 tcg_gen_add_i64(rh
, rh
, t1
);
2530 tcg_gen_mov_i64(rl
, t0
);
2531 tcg_temp_free_i64(t0
);
2532 tcg_temp_free_i64(t1
);
2536 void tcg_gen_sub2_i64(TCGv_i64 rl
, TCGv_i64 rh
, TCGv_i64 al
,
2537 TCGv_i64 ah
, TCGv_i64 bl
, TCGv_i64 bh
)
2539 if (TCG_TARGET_HAS_sub2_i64
) {
2540 tcg_gen_op6_i64(INDEX_op_sub2_i64
, rl
, rh
, al
, ah
, bl
, bh
);
2542 TCGv_i64 t0
= tcg_temp_new_i64();
2543 TCGv_i64 t1
= tcg_temp_new_i64();
2544 tcg_gen_sub_i64(t0
, al
, bl
);
2545 tcg_gen_setcond_i64(TCG_COND_LTU
, t1
, al
, bl
);
2546 tcg_gen_sub_i64(rh
, ah
, bh
);
2547 tcg_gen_sub_i64(rh
, rh
, t1
);
2548 tcg_gen_mov_i64(rl
, t0
);
2549 tcg_temp_free_i64(t0
);
2550 tcg_temp_free_i64(t1
);
2554 void tcg_gen_mulu2_i64(TCGv_i64 rl
, TCGv_i64 rh
, TCGv_i64 arg1
, TCGv_i64 arg2
)
2556 if (TCG_TARGET_HAS_mulu2_i64
) {
2557 tcg_gen_op4_i64(INDEX_op_mulu2_i64
, rl
, rh
, arg1
, arg2
);
2558 } else if (TCG_TARGET_HAS_muluh_i64
) {
2559 TCGv_i64 t
= tcg_temp_new_i64();
2560 tcg_gen_op3_i64(INDEX_op_mul_i64
, t
, arg1
, arg2
);
2561 tcg_gen_op3_i64(INDEX_op_muluh_i64
, rh
, arg1
, arg2
);
2562 tcg_gen_mov_i64(rl
, t
);
2563 tcg_temp_free_i64(t
);
2565 TCGv_i64 t0
= tcg_temp_new_i64();
2566 tcg_gen_mul_i64(t0
, arg1
, arg2
);
2567 gen_helper_muluh_i64(rh
, arg1
, arg2
);
2568 tcg_gen_mov_i64(rl
, t0
);
2569 tcg_temp_free_i64(t0
);
2573 void tcg_gen_muls2_i64(TCGv_i64 rl
, TCGv_i64 rh
, TCGv_i64 arg1
, TCGv_i64 arg2
)
2575 if (TCG_TARGET_HAS_muls2_i64
) {
2576 tcg_gen_op4_i64(INDEX_op_muls2_i64
, rl
, rh
, arg1
, arg2
);
2577 } else if (TCG_TARGET_HAS_mulsh_i64
) {
2578 TCGv_i64 t
= tcg_temp_new_i64();
2579 tcg_gen_op3_i64(INDEX_op_mul_i64
, t
, arg1
, arg2
);
2580 tcg_gen_op3_i64(INDEX_op_mulsh_i64
, rh
, arg1
, arg2
);
2581 tcg_gen_mov_i64(rl
, t
);
2582 tcg_temp_free_i64(t
);
2583 } else if (TCG_TARGET_HAS_mulu2_i64
|| TCG_TARGET_HAS_muluh_i64
) {
2584 TCGv_i64 t0
= tcg_temp_new_i64();
2585 TCGv_i64 t1
= tcg_temp_new_i64();
2586 TCGv_i64 t2
= tcg_temp_new_i64();
2587 TCGv_i64 t3
= tcg_temp_new_i64();
2588 tcg_gen_mulu2_i64(t0
, t1
, arg1
, arg2
);
2589 /* Adjust for negative inputs. */
2590 tcg_gen_sari_i64(t2
, arg1
, 63);
2591 tcg_gen_sari_i64(t3
, arg2
, 63);
2592 tcg_gen_and_i64(t2
, t2
, arg2
);
2593 tcg_gen_and_i64(t3
, t3
, arg1
);
2594 tcg_gen_sub_i64(rh
, t1
, t2
);
2595 tcg_gen_sub_i64(rh
, rh
, t3
);
2596 tcg_gen_mov_i64(rl
, t0
);
2597 tcg_temp_free_i64(t0
);
2598 tcg_temp_free_i64(t1
);
2599 tcg_temp_free_i64(t2
);
2600 tcg_temp_free_i64(t3
);
2602 TCGv_i64 t0
= tcg_temp_new_i64();
2603 tcg_gen_mul_i64(t0
, arg1
, arg2
);
2604 gen_helper_mulsh_i64(rh
, arg1
, arg2
);
2605 tcg_gen_mov_i64(rl
, t0
);
2606 tcg_temp_free_i64(t0
);
2610 void tcg_gen_mulsu2_i64(TCGv_i64 rl
, TCGv_i64 rh
, TCGv_i64 arg1
, TCGv_i64 arg2
)
2612 TCGv_i64 t0
= tcg_temp_new_i64();
2613 TCGv_i64 t1
= tcg_temp_new_i64();
2614 TCGv_i64 t2
= tcg_temp_new_i64();
2615 tcg_gen_mulu2_i64(t0
, t1
, arg1
, arg2
);
2616 /* Adjust for negative input for the signed arg1. */
2617 tcg_gen_sari_i64(t2
, arg1
, 63);
2618 tcg_gen_and_i64(t2
, t2
, arg2
);
2619 tcg_gen_sub_i64(rh
, t1
, t2
);
2620 tcg_gen_mov_i64(rl
, t0
);
2621 tcg_temp_free_i64(t0
);
2622 tcg_temp_free_i64(t1
);
2623 tcg_temp_free_i64(t2
);
2626 void tcg_gen_smin_i64(TCGv_i64 ret
, TCGv_i64 a
, TCGv_i64 b
)
2628 tcg_gen_movcond_i64(TCG_COND_LT
, ret
, a
, b
, a
, b
);
2631 void tcg_gen_umin_i64(TCGv_i64 ret
, TCGv_i64 a
, TCGv_i64 b
)
2633 tcg_gen_movcond_i64(TCG_COND_LTU
, ret
, a
, b
, a
, b
);
2636 void tcg_gen_smax_i64(TCGv_i64 ret
, TCGv_i64 a
, TCGv_i64 b
)
2638 tcg_gen_movcond_i64(TCG_COND_LT
, ret
, a
, b
, b
, a
);
2641 void tcg_gen_umax_i64(TCGv_i64 ret
, TCGv_i64 a
, TCGv_i64 b
)
2643 tcg_gen_movcond_i64(TCG_COND_LTU
, ret
, a
, b
, b
, a
);
2646 void tcg_gen_abs_i64(TCGv_i64 ret
, TCGv_i64 a
)
2648 TCGv_i64 t
= tcg_temp_new_i64();
2650 tcg_gen_sari_i64(t
, a
, 63);
2651 tcg_gen_xor_i64(ret
, a
, t
);
2652 tcg_gen_sub_i64(ret
, ret
, t
);
2653 tcg_temp_free_i64(t
);
2656 /* Size changing operations. */
2658 void tcg_gen_extrl_i64_i32(TCGv_i32 ret
, TCGv_i64 arg
)
2660 if (TCG_TARGET_REG_BITS
== 32) {
2661 tcg_gen_mov_i32(ret
, TCGV_LOW(arg
));
2662 } else if (TCG_TARGET_HAS_extrl_i64_i32
) {
2663 tcg_gen_op2(INDEX_op_extrl_i64_i32
,
2664 tcgv_i32_arg(ret
), tcgv_i64_arg(arg
));
2666 tcg_gen_mov_i32(ret
, (TCGv_i32
)arg
);
2670 void tcg_gen_extrh_i64_i32(TCGv_i32 ret
, TCGv_i64 arg
)
2672 if (TCG_TARGET_REG_BITS
== 32) {
2673 tcg_gen_mov_i32(ret
, TCGV_HIGH(arg
));
2674 } else if (TCG_TARGET_HAS_extrh_i64_i32
) {
2675 tcg_gen_op2(INDEX_op_extrh_i64_i32
,
2676 tcgv_i32_arg(ret
), tcgv_i64_arg(arg
));
2678 TCGv_i64 t
= tcg_temp_new_i64();
2679 tcg_gen_shri_i64(t
, arg
, 32);
2680 tcg_gen_mov_i32(ret
, (TCGv_i32
)t
);
2681 tcg_temp_free_i64(t
);
2685 void tcg_gen_extu_i32_i64(TCGv_i64 ret
, TCGv_i32 arg
)
2687 if (TCG_TARGET_REG_BITS
== 32) {
2688 tcg_gen_mov_i32(TCGV_LOW(ret
), arg
);
2689 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
2691 tcg_gen_op2(INDEX_op_extu_i32_i64
,
2692 tcgv_i64_arg(ret
), tcgv_i32_arg(arg
));
2696 void tcg_gen_ext_i32_i64(TCGv_i64 ret
, TCGv_i32 arg
)
2698 if (TCG_TARGET_REG_BITS
== 32) {
2699 tcg_gen_mov_i32(TCGV_LOW(ret
), arg
);
2700 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_LOW(ret
), 31);
2702 tcg_gen_op2(INDEX_op_ext_i32_i64
,
2703 tcgv_i64_arg(ret
), tcgv_i32_arg(arg
));
2707 void tcg_gen_concat_i32_i64(TCGv_i64 dest
, TCGv_i32 low
, TCGv_i32 high
)
2711 if (TCG_TARGET_REG_BITS
== 32) {
2712 tcg_gen_mov_i32(TCGV_LOW(dest
), low
);
2713 tcg_gen_mov_i32(TCGV_HIGH(dest
), high
);
2717 tmp
= tcg_temp_new_i64();
2718 /* These extensions are only needed for type correctness.
2719 We may be able to do better given target specific information. */
2720 tcg_gen_extu_i32_i64(tmp
, high
);
2721 tcg_gen_extu_i32_i64(dest
, low
);
2722 /* If deposit is available, use it. Otherwise use the extra
2723 knowledge that we have of the zero-extensions above. */
2724 if (TCG_TARGET_HAS_deposit_i64
&& TCG_TARGET_deposit_i64_valid(32, 32)) {
2725 tcg_gen_deposit_i64(dest
, dest
, tmp
, 32, 32);
2727 tcg_gen_shli_i64(tmp
, tmp
, 32);
2728 tcg_gen_or_i64(dest
, dest
, tmp
);
2730 tcg_temp_free_i64(tmp
);
2733 void tcg_gen_extr_i64_i32(TCGv_i32 lo
, TCGv_i32 hi
, TCGv_i64 arg
)
2735 if (TCG_TARGET_REG_BITS
== 32) {
2736 tcg_gen_mov_i32(lo
, TCGV_LOW(arg
));
2737 tcg_gen_mov_i32(hi
, TCGV_HIGH(arg
));
2739 tcg_gen_extrl_i64_i32(lo
, arg
);
2740 tcg_gen_extrh_i64_i32(hi
, arg
);
2744 void tcg_gen_extr32_i64(TCGv_i64 lo
, TCGv_i64 hi
, TCGv_i64 arg
)
2746 tcg_gen_ext32u_i64(lo
, arg
);
2747 tcg_gen_shri_i64(hi
, arg
, 32);
2750 void tcg_gen_extr_i128_i64(TCGv_i64 lo
, TCGv_i64 hi
, TCGv_i128 arg
)
2752 tcg_gen_mov_i64(lo
, TCGV128_LOW(arg
));
2753 tcg_gen_mov_i64(hi
, TCGV128_HIGH(arg
));
2756 void tcg_gen_concat_i64_i128(TCGv_i128 ret
, TCGv_i64 lo
, TCGv_i64 hi
)
2758 tcg_gen_mov_i64(TCGV128_LOW(ret
), lo
);
2759 tcg_gen_mov_i64(TCGV128_HIGH(ret
), hi
);
2762 void tcg_gen_mov_i128(TCGv_i128 dst
, TCGv_i128 src
)
2765 tcg_gen_mov_i64(TCGV128_LOW(dst
), TCGV128_LOW(src
));
2766 tcg_gen_mov_i64(TCGV128_HIGH(dst
), TCGV128_HIGH(src
));
2770 /* QEMU specific operations. */
2772 void tcg_gen_exit_tb(const TranslationBlock
*tb
, unsigned idx
)
2775 * Let the jit code return the read-only version of the
2776 * TranslationBlock, so that we minimize the pc-relative
2777 * distance of the address of the exit_tb code to TB.
2778 * This will improve utilization of pc-relative address loads.
2780 * TODO: Move this to translator_loop, so that all const
2781 * TranslationBlock pointers refer to read-only memory.
2782 * This requires coordination with targets that do not use
2783 * the translator_loop.
2785 uintptr_t val
= (uintptr_t)tcg_splitwx_to_rx((void *)tb
) + idx
;
2788 tcg_debug_assert(idx
== 0);
2789 } else if (idx
<= TB_EXIT_IDXMAX
) {
2790 #ifdef CONFIG_DEBUG_TCG
2791 /* This is an exit following a goto_tb. Verify that we have
2792 seen this numbered exit before, via tcg_gen_goto_tb. */
2793 tcg_debug_assert(tcg_ctx
->goto_tb_issue_mask
& (1 << idx
));
2796 /* This is an exit via the exitreq label. */
2797 tcg_debug_assert(idx
== TB_EXIT_REQUESTED
);
2800 plugin_gen_disable_mem_helpers();
2801 tcg_gen_op1i(INDEX_op_exit_tb
, val
);
2804 void tcg_gen_goto_tb(unsigned idx
)
2806 /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
2807 tcg_debug_assert(!(tcg_ctx
->gen_tb
->cflags
& CF_NO_GOTO_TB
));
2808 /* We only support two chained exits. */
2809 tcg_debug_assert(idx
<= TB_EXIT_IDXMAX
);
2810 #ifdef CONFIG_DEBUG_TCG
2811 /* Verify that we haven't seen this numbered exit before. */
2812 tcg_debug_assert((tcg_ctx
->goto_tb_issue_mask
& (1 << idx
)) == 0);
2813 tcg_ctx
->goto_tb_issue_mask
|= 1 << idx
;
2815 plugin_gen_disable_mem_helpers();
2816 tcg_gen_op1i(INDEX_op_goto_tb
, idx
);
2819 void tcg_gen_lookup_and_goto_ptr(void)
2823 if (tcg_ctx
->gen_tb
->cflags
& CF_NO_GOTO_PTR
) {
2824 tcg_gen_exit_tb(NULL
, 0);
2828 plugin_gen_disable_mem_helpers();
2829 ptr
= tcg_temp_new_ptr();
2830 gen_helper_lookup_tb_ptr(ptr
, cpu_env
);
2831 tcg_gen_op1i(INDEX_op_goto_ptr
, tcgv_ptr_arg(ptr
));
2832 tcg_temp_free_ptr(ptr
);
2835 static inline MemOp
tcg_canonicalize_memop(MemOp op
, bool is64
, bool st
)
2837 /* Trigger the asserts within as early as possible. */
2838 unsigned a_bits
= get_alignment_bits(op
);
2840 /* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */
2841 if (a_bits
== (op
& MO_SIZE
)) {
2842 op
= (op
& ~MO_AMASK
) | MO_ALIGN
;
2845 switch (op
& MO_SIZE
) {
2863 g_assert_not_reached();
2871 static void gen_ldst_i32(TCGOpcode opc
, TCGv_i32 val
, TCGv addr
,
2872 MemOp memop
, TCGArg idx
)
2874 MemOpIdx oi
= make_memop_idx(memop
, idx
);
2875 #if TARGET_LONG_BITS == 32
2876 tcg_gen_op3i_i32(opc
, val
, addr
, oi
);
2878 if (TCG_TARGET_REG_BITS
== 32) {
2879 tcg_gen_op4i_i32(opc
, val
, TCGV_LOW(addr
), TCGV_HIGH(addr
), oi
);
2881 tcg_gen_op3(opc
, tcgv_i32_arg(val
), tcgv_i64_arg(addr
), oi
);
2886 static void gen_ldst_i64(TCGOpcode opc
, TCGv_i64 val
, TCGv addr
,
2887 MemOp memop
, TCGArg idx
)
2889 MemOpIdx oi
= make_memop_idx(memop
, idx
);
2890 #if TARGET_LONG_BITS == 32
2891 if (TCG_TARGET_REG_BITS
== 32) {
2892 tcg_gen_op4i_i32(opc
, TCGV_LOW(val
), TCGV_HIGH(val
), addr
, oi
);
2894 tcg_gen_op3(opc
, tcgv_i64_arg(val
), tcgv_i32_arg(addr
), oi
);
2897 if (TCG_TARGET_REG_BITS
== 32) {
2898 tcg_gen_op5i_i32(opc
, TCGV_LOW(val
), TCGV_HIGH(val
),
2899 TCGV_LOW(addr
), TCGV_HIGH(addr
), oi
);
2901 tcg_gen_op3i_i64(opc
, val
, addr
, oi
);
2906 static void tcg_gen_req_mo(TCGBar type
)
2908 #ifdef TCG_GUEST_DEFAULT_MO
2909 type
&= TCG_GUEST_DEFAULT_MO
;
2911 type
&= ~TCG_TARGET_DEFAULT_MO
;
2913 tcg_gen_mb(type
| TCG_BAR_SC
);
2917 static inline TCGv
plugin_prep_mem_callbacks(TCGv vaddr
)
2919 #ifdef CONFIG_PLUGIN
2920 if (tcg_ctx
->plugin_insn
!= NULL
) {
2921 /* Save a copy of the vaddr for use after a load. */
2922 TCGv temp
= tcg_temp_new();
2923 tcg_gen_mov_tl(temp
, vaddr
);
2930 static void plugin_gen_mem_callbacks(TCGv vaddr
, MemOpIdx oi
,
2931 enum qemu_plugin_mem_rw rw
)
2933 #ifdef CONFIG_PLUGIN
2934 if (tcg_ctx
->plugin_insn
!= NULL
) {
2935 qemu_plugin_meminfo_t info
= make_plugin_meminfo(oi
, rw
);
2936 plugin_gen_empty_mem_callback(vaddr
, info
);
2937 tcg_temp_free(vaddr
);
2942 void tcg_gen_qemu_ld_i32(TCGv_i32 val
, TCGv addr
, TCGArg idx
, MemOp memop
)
2947 tcg_gen_req_mo(TCG_MO_LD_LD
| TCG_MO_ST_LD
);
2948 memop
= tcg_canonicalize_memop(memop
, 0, 0);
2949 oi
= make_memop_idx(memop
, idx
);
2952 if (!TCG_TARGET_HAS_MEMORY_BSWAP
&& (memop
& MO_BSWAP
)) {
2954 /* The bswap primitive benefits from zero-extended input. */
2955 if ((memop
& MO_SSIZE
) == MO_SW
) {
2960 addr
= plugin_prep_mem_callbacks(addr
);
2961 gen_ldst_i32(INDEX_op_qemu_ld_i32
, val
, addr
, memop
, idx
);
2962 plugin_gen_mem_callbacks(addr
, oi
, QEMU_PLUGIN_MEM_R
);
2964 if ((orig_memop
^ memop
) & MO_BSWAP
) {
2965 switch (orig_memop
& MO_SIZE
) {
2967 tcg_gen_bswap16_i32(val
, val
, (orig_memop
& MO_SIGN
2968 ? TCG_BSWAP_IZ
| TCG_BSWAP_OS
2969 : TCG_BSWAP_IZ
| TCG_BSWAP_OZ
));
2972 tcg_gen_bswap32_i32(val
, val
);
2975 g_assert_not_reached();
2980 void tcg_gen_qemu_st_i32(TCGv_i32 val
, TCGv addr
, TCGArg idx
, MemOp memop
)
2982 TCGv_i32 swap
= NULL
;
2985 tcg_gen_req_mo(TCG_MO_LD_ST
| TCG_MO_ST_ST
);
2986 memop
= tcg_canonicalize_memop(memop
, 0, 1);
2987 oi
= make_memop_idx(memop
, idx
);
2989 if (!TCG_TARGET_HAS_MEMORY_BSWAP
&& (memop
& MO_BSWAP
)) {
2990 swap
= tcg_temp_new_i32();
2991 switch (memop
& MO_SIZE
) {
2993 tcg_gen_bswap16_i32(swap
, val
, 0);
2996 tcg_gen_bswap32_i32(swap
, val
);
2999 g_assert_not_reached();
3005 addr
= plugin_prep_mem_callbacks(addr
);
3006 if (TCG_TARGET_HAS_qemu_st8_i32
&& (memop
& MO_SIZE
) == MO_8
) {
3007 gen_ldst_i32(INDEX_op_qemu_st8_i32
, val
, addr
, memop
, idx
);
3009 gen_ldst_i32(INDEX_op_qemu_st_i32
, val
, addr
, memop
, idx
);
3011 plugin_gen_mem_callbacks(addr
, oi
, QEMU_PLUGIN_MEM_W
);
3014 tcg_temp_free_i32(swap
);
3018 void tcg_gen_qemu_ld_i64(TCGv_i64 val
, TCGv addr
, TCGArg idx
, MemOp memop
)
3023 if (TCG_TARGET_REG_BITS
== 32 && (memop
& MO_SIZE
) < MO_64
) {
3024 tcg_gen_qemu_ld_i32(TCGV_LOW(val
), addr
, idx
, memop
);
3025 if (memop
& MO_SIGN
) {
3026 tcg_gen_sari_i32(TCGV_HIGH(val
), TCGV_LOW(val
), 31);
3028 tcg_gen_movi_i32(TCGV_HIGH(val
), 0);
3033 tcg_gen_req_mo(TCG_MO_LD_LD
| TCG_MO_ST_LD
);
3034 memop
= tcg_canonicalize_memop(memop
, 1, 0);
3035 oi
= make_memop_idx(memop
, idx
);
3038 if (!TCG_TARGET_HAS_MEMORY_BSWAP
&& (memop
& MO_BSWAP
)) {
3040 /* The bswap primitive benefits from zero-extended input. */
3041 if ((memop
& MO_SIGN
) && (memop
& MO_SIZE
) < MO_64
) {
3046 addr
= plugin_prep_mem_callbacks(addr
);
3047 gen_ldst_i64(INDEX_op_qemu_ld_i64
, val
, addr
, memop
, idx
);
3048 plugin_gen_mem_callbacks(addr
, oi
, QEMU_PLUGIN_MEM_R
);
3050 if ((orig_memop
^ memop
) & MO_BSWAP
) {
3051 int flags
= (orig_memop
& MO_SIGN
3052 ? TCG_BSWAP_IZ
| TCG_BSWAP_OS
3053 : TCG_BSWAP_IZ
| TCG_BSWAP_OZ
);
3054 switch (orig_memop
& MO_SIZE
) {
3056 tcg_gen_bswap16_i64(val
, val
, flags
);
3059 tcg_gen_bswap32_i64(val
, val
, flags
);
3062 tcg_gen_bswap64_i64(val
, val
);
3065 g_assert_not_reached();
3070 void tcg_gen_qemu_st_i64(TCGv_i64 val
, TCGv addr
, TCGArg idx
, MemOp memop
)
3072 TCGv_i64 swap
= NULL
;
3075 if (TCG_TARGET_REG_BITS
== 32 && (memop
& MO_SIZE
) < MO_64
) {
3076 tcg_gen_qemu_st_i32(TCGV_LOW(val
), addr
, idx
, memop
);
3080 tcg_gen_req_mo(TCG_MO_LD_ST
| TCG_MO_ST_ST
);
3081 memop
= tcg_canonicalize_memop(memop
, 1, 1);
3082 oi
= make_memop_idx(memop
, idx
);
3084 if (!TCG_TARGET_HAS_MEMORY_BSWAP
&& (memop
& MO_BSWAP
)) {
3085 swap
= tcg_temp_new_i64();
3086 switch (memop
& MO_SIZE
) {
3088 tcg_gen_bswap16_i64(swap
, val
, 0);
3091 tcg_gen_bswap32_i64(swap
, val
, 0);
3094 tcg_gen_bswap64_i64(swap
, val
);
3097 g_assert_not_reached();
3103 addr
= plugin_prep_mem_callbacks(addr
);
3104 gen_ldst_i64(INDEX_op_qemu_st_i64
, val
, addr
, memop
, idx
);
3105 plugin_gen_mem_callbacks(addr
, oi
, QEMU_PLUGIN_MEM_W
);
3108 tcg_temp_free_i64(swap
);
3112 static void canonicalize_memop_i128_as_i64(MemOp ret
[2], MemOp orig
)
3114 MemOp mop_1
= orig
, mop_2
;
3116 tcg_debug_assert((orig
& MO_SIZE
) == MO_128
);
3117 tcg_debug_assert((orig
& MO_SIGN
) == 0);
3119 /* Use a memory ordering implemented by the host. */
3120 if (!TCG_TARGET_HAS_MEMORY_BSWAP
&& (orig
& MO_BSWAP
)) {
3124 /* Reduce the size to 64-bit. */
3125 mop_1
= (mop_1
& ~MO_SIZE
) | MO_64
;
3127 /* Retain the alignment constraints of the original. */
3128 switch (orig
& MO_AMASK
) {
3135 /* Prefer MO_ALIGN+MO_64 to MO_ALIGN_8+MO_64. */
3136 mop_1
= (mop_1
& ~MO_AMASK
) | MO_ALIGN
;
3140 /* Second has 8-byte alignment; first has 16-byte alignment. */
3142 mop_1
= (mop_1
& ~MO_AMASK
) | MO_ALIGN_16
;
3147 /* Second has 8-byte alignment; first retains original. */
3148 mop_2
= (mop_1
& ~MO_AMASK
) | MO_ALIGN
;
3151 g_assert_not_reached();
3157 void tcg_gen_qemu_ld_i128(TCGv_i128 val
, TCGv addr
, TCGArg idx
, MemOp memop
)
3163 canonicalize_memop_i128_as_i64(mop
, memop
);
3165 tcg_gen_req_mo(TCG_MO_LD_LD
| TCG_MO_ST_LD
);
3166 addr
= plugin_prep_mem_callbacks(addr
);
3168 /* TODO: respect atomicity of the operation. */
3169 /* TODO: allow the tcg backend to see the whole operation. */
3172 * Since there are no global TCGv_i128, there is no visible state
3173 * changed if the second load faults. Load directly into the two
3176 if ((memop
& MO_BSWAP
) == MO_LE
) {
3177 x
= TCGV128_LOW(val
);
3178 y
= TCGV128_HIGH(val
);
3180 x
= TCGV128_HIGH(val
);
3181 y
= TCGV128_LOW(val
);
3184 gen_ldst_i64(INDEX_op_qemu_ld_i64
, x
, addr
, mop
[0], idx
);
3186 if ((mop
[0] ^ memop
) & MO_BSWAP
) {
3187 tcg_gen_bswap64_i64(x
, x
);
3190 addr_p8
= tcg_temp_new();
3191 tcg_gen_addi_tl(addr_p8
, addr
, 8);
3192 gen_ldst_i64(INDEX_op_qemu_ld_i64
, y
, addr_p8
, mop
[1], idx
);
3193 tcg_temp_free(addr_p8
);
3195 if ((mop
[0] ^ memop
) & MO_BSWAP
) {
3196 tcg_gen_bswap64_i64(y
, y
);
3199 plugin_gen_mem_callbacks(addr
, make_memop_idx(memop
, idx
),
3203 void tcg_gen_qemu_st_i128(TCGv_i128 val
, TCGv addr
, TCGArg idx
, MemOp memop
)
3209 canonicalize_memop_i128_as_i64(mop
, memop
);
3211 tcg_gen_req_mo(TCG_MO_ST_LD
| TCG_MO_ST_ST
);
3212 addr
= plugin_prep_mem_callbacks(addr
);
3214 /* TODO: respect atomicity of the operation. */
3215 /* TODO: allow the tcg backend to see the whole operation. */
3217 if ((memop
& MO_BSWAP
) == MO_LE
) {
3218 x
= TCGV128_LOW(val
);
3219 y
= TCGV128_HIGH(val
);
3221 x
= TCGV128_HIGH(val
);
3222 y
= TCGV128_LOW(val
);
3225 addr_p8
= tcg_temp_new();
3226 if ((mop
[0] ^ memop
) & MO_BSWAP
) {
3227 TCGv_i64 t
= tcg_temp_new_i64();
3229 tcg_gen_bswap64_i64(t
, x
);
3230 gen_ldst_i64(INDEX_op_qemu_st_i64
, t
, addr
, mop
[0], idx
);
3231 tcg_gen_bswap64_i64(t
, y
);
3232 tcg_gen_addi_tl(addr_p8
, addr
, 8);
3233 gen_ldst_i64(INDEX_op_qemu_st_i64
, t
, addr_p8
, mop
[1], idx
);
3234 tcg_temp_free_i64(t
);
3236 gen_ldst_i64(INDEX_op_qemu_st_i64
, x
, addr
, mop
[0], idx
);
3237 tcg_gen_addi_tl(addr_p8
, addr
, 8);
3238 gen_ldst_i64(INDEX_op_qemu_st_i64
, y
, addr_p8
, mop
[1], idx
);
3240 tcg_temp_free(addr_p8
);
3242 plugin_gen_mem_callbacks(addr
, make_memop_idx(memop
, idx
),
3246 static void tcg_gen_ext_i32(TCGv_i32 ret
, TCGv_i32 val
, MemOp opc
)
3248 switch (opc
& MO_SSIZE
) {
3250 tcg_gen_ext8s_i32(ret
, val
);
3253 tcg_gen_ext8u_i32(ret
, val
);
3256 tcg_gen_ext16s_i32(ret
, val
);
3259 tcg_gen_ext16u_i32(ret
, val
);
3262 tcg_gen_mov_i32(ret
, val
);
3267 static void tcg_gen_ext_i64(TCGv_i64 ret
, TCGv_i64 val
, MemOp opc
)
3269 switch (opc
& MO_SSIZE
) {
3271 tcg_gen_ext8s_i64(ret
, val
);
3274 tcg_gen_ext8u_i64(ret
, val
);
3277 tcg_gen_ext16s_i64(ret
, val
);
3280 tcg_gen_ext16u_i64(ret
, val
);
3283 tcg_gen_ext32s_i64(ret
, val
);
3286 tcg_gen_ext32u_i64(ret
, val
);
3289 tcg_gen_mov_i64(ret
, val
);
3294 typedef void (*gen_atomic_cx_i32
)(TCGv_i32
, TCGv_env
, TCGv
,
3295 TCGv_i32
, TCGv_i32
, TCGv_i32
);
3296 typedef void (*gen_atomic_cx_i64
)(TCGv_i64
, TCGv_env
, TCGv
,
3297 TCGv_i64
, TCGv_i64
, TCGv_i32
);
3298 typedef void (*gen_atomic_cx_i128
)(TCGv_i128
, TCGv_env
, TCGv
,
3299 TCGv_i128
, TCGv_i128
, TCGv_i32
);
3300 typedef void (*gen_atomic_op_i32
)(TCGv_i32
, TCGv_env
, TCGv
,
3301 TCGv_i32
, TCGv_i32
);
3302 typedef void (*gen_atomic_op_i64
)(TCGv_i64
, TCGv_env
, TCGv
,
3303 TCGv_i64
, TCGv_i32
);
3305 #ifdef CONFIG_ATOMIC64
3306 # define WITH_ATOMIC64(X) X,
3308 # define WITH_ATOMIC64(X)
3310 #ifdef CONFIG_CMPXCHG128
3311 # define WITH_ATOMIC128(X) X,
3313 # define WITH_ATOMIC128(X)
3316 static void * const table_cmpxchg
[(MO_SIZE
| MO_BSWAP
) + 1] = {
3317 [MO_8
] = gen_helper_atomic_cmpxchgb
,
3318 [MO_16
| MO_LE
] = gen_helper_atomic_cmpxchgw_le
,
3319 [MO_16
| MO_BE
] = gen_helper_atomic_cmpxchgw_be
,
3320 [MO_32
| MO_LE
] = gen_helper_atomic_cmpxchgl_le
,
3321 [MO_32
| MO_BE
] = gen_helper_atomic_cmpxchgl_be
,
3322 WITH_ATOMIC64([MO_64
| MO_LE
] = gen_helper_atomic_cmpxchgq_le
)
3323 WITH_ATOMIC64([MO_64
| MO_BE
] = gen_helper_atomic_cmpxchgq_be
)
3324 WITH_ATOMIC128([MO_128
| MO_LE
] = gen_helper_atomic_cmpxchgo_le
)
3325 WITH_ATOMIC128([MO_128
| MO_BE
] = gen_helper_atomic_cmpxchgo_be
)
3328 void tcg_gen_nonatomic_cmpxchg_i32(TCGv_i32 retv
, TCGv addr
, TCGv_i32 cmpv
,
3329 TCGv_i32 newv
, TCGArg idx
, MemOp memop
)
3331 TCGv_i32 t1
= tcg_temp_new_i32();
3332 TCGv_i32 t2
= tcg_temp_new_i32();
3334 tcg_gen_ext_i32(t2
, cmpv
, memop
& MO_SIZE
);
3336 tcg_gen_qemu_ld_i32(t1
, addr
, idx
, memop
& ~MO_SIGN
);
3337 tcg_gen_movcond_i32(TCG_COND_EQ
, t2
, t1
, t2
, newv
, t1
);
3338 tcg_gen_qemu_st_i32(t2
, addr
, idx
, memop
);
3339 tcg_temp_free_i32(t2
);
3341 if (memop
& MO_SIGN
) {
3342 tcg_gen_ext_i32(retv
, t1
, memop
);
3344 tcg_gen_mov_i32(retv
, t1
);
3346 tcg_temp_free_i32(t1
);
3349 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv
, TCGv addr
, TCGv_i32 cmpv
,
3350 TCGv_i32 newv
, TCGArg idx
, MemOp memop
)
3352 gen_atomic_cx_i32 gen
;
3355 if (!(tcg_ctx
->gen_tb
->cflags
& CF_PARALLEL
)) {
3356 tcg_gen_nonatomic_cmpxchg_i32(retv
, addr
, cmpv
, newv
, idx
, memop
);
3360 memop
= tcg_canonicalize_memop(memop
, 0, 0);
3361 gen
= table_cmpxchg
[memop
& (MO_SIZE
| MO_BSWAP
)];
3362 tcg_debug_assert(gen
!= NULL
);
3364 oi
= make_memop_idx(memop
& ~MO_SIGN
, idx
);
3365 gen(retv
, cpu_env
, addr
, cmpv
, newv
, tcg_constant_i32(oi
));
3367 if (memop
& MO_SIGN
) {
3368 tcg_gen_ext_i32(retv
, retv
, memop
);
3372 void tcg_gen_nonatomic_cmpxchg_i64(TCGv_i64 retv
, TCGv addr
, TCGv_i64 cmpv
,
3373 TCGv_i64 newv
, TCGArg idx
, MemOp memop
)
3377 if (TCG_TARGET_REG_BITS
== 32 && (memop
& MO_SIZE
) < MO_64
) {
3378 tcg_gen_nonatomic_cmpxchg_i32(TCGV_LOW(retv
), addr
, TCGV_LOW(cmpv
),
3379 TCGV_LOW(newv
), idx
, memop
);
3380 if (memop
& MO_SIGN
) {
3381 tcg_gen_sari_i32(TCGV_HIGH(retv
), TCGV_LOW(retv
), 31);
3383 tcg_gen_movi_i32(TCGV_HIGH(retv
), 0);
3388 t1
= tcg_temp_new_i64();
3389 t2
= tcg_temp_new_i64();
3391 tcg_gen_ext_i64(t2
, cmpv
, memop
& MO_SIZE
);
3393 tcg_gen_qemu_ld_i64(t1
, addr
, idx
, memop
& ~MO_SIGN
);
3394 tcg_gen_movcond_i64(TCG_COND_EQ
, t2
, t1
, t2
, newv
, t1
);
3395 tcg_gen_qemu_st_i64(t2
, addr
, idx
, memop
);
3396 tcg_temp_free_i64(t2
);
3398 if (memop
& MO_SIGN
) {
3399 tcg_gen_ext_i64(retv
, t1
, memop
);
3401 tcg_gen_mov_i64(retv
, t1
);
3403 tcg_temp_free_i64(t1
);
3406 void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv
, TCGv addr
, TCGv_i64 cmpv
,
3407 TCGv_i64 newv
, TCGArg idx
, MemOp memop
)
3409 if (!(tcg_ctx
->gen_tb
->cflags
& CF_PARALLEL
)) {
3410 tcg_gen_nonatomic_cmpxchg_i64(retv
, addr
, cmpv
, newv
, idx
, memop
);
3414 if ((memop
& MO_SIZE
) == MO_64
) {
3415 gen_atomic_cx_i64 gen
;
3417 memop
= tcg_canonicalize_memop(memop
, 1, 0);
3418 gen
= table_cmpxchg
[memop
& (MO_SIZE
| MO_BSWAP
)];
3420 MemOpIdx oi
= make_memop_idx(memop
, idx
);
3421 gen(retv
, cpu_env
, addr
, cmpv
, newv
, tcg_constant_i32(oi
));
3425 gen_helper_exit_atomic(cpu_env
);
3428 * Produce a result for a well-formed opcode stream. This satisfies
3429 * liveness for set before used, which happens before this dead code
3432 tcg_gen_movi_i64(retv
, 0);
3436 if (TCG_TARGET_REG_BITS
== 32) {
3437 tcg_gen_atomic_cmpxchg_i32(TCGV_LOW(retv
), addr
, TCGV_LOW(cmpv
),
3438 TCGV_LOW(newv
), idx
, memop
);
3439 if (memop
& MO_SIGN
) {
3440 tcg_gen_sari_i32(TCGV_HIGH(retv
), TCGV_LOW(retv
), 31);
3442 tcg_gen_movi_i32(TCGV_HIGH(retv
), 0);
3445 TCGv_i32 c32
= tcg_temp_new_i32();
3446 TCGv_i32 n32
= tcg_temp_new_i32();
3447 TCGv_i32 r32
= tcg_temp_new_i32();
3449 tcg_gen_extrl_i64_i32(c32
, cmpv
);
3450 tcg_gen_extrl_i64_i32(n32
, newv
);
3451 tcg_gen_atomic_cmpxchg_i32(r32
, addr
, c32
, n32
, idx
, memop
& ~MO_SIGN
);
3452 tcg_temp_free_i32(c32
);
3453 tcg_temp_free_i32(n32
);
3455 tcg_gen_extu_i32_i64(retv
, r32
);
3456 tcg_temp_free_i32(r32
);
3458 if (memop
& MO_SIGN
) {
3459 tcg_gen_ext_i64(retv
, retv
, memop
);
3464 void tcg_gen_nonatomic_cmpxchg_i128(TCGv_i128 retv
, TCGv addr
, TCGv_i128 cmpv
,
3465 TCGv_i128 newv
, TCGArg idx
, MemOp memop
)
3467 if (TCG_TARGET_REG_BITS
== 32) {
3468 /* Inline expansion below is simply too large for 32-bit hosts. */
3469 gen_atomic_cx_i128 gen
= ((memop
& MO_BSWAP
) == MO_LE
3470 ? gen_helper_nonatomic_cmpxchgo_le
3471 : gen_helper_nonatomic_cmpxchgo_be
);
3472 MemOpIdx oi
= make_memop_idx(memop
, idx
);
3474 tcg_debug_assert((memop
& MO_SIZE
) == MO_128
);
3475 tcg_debug_assert((memop
& MO_SIGN
) == 0);
3477 gen(retv
, cpu_env
, addr
, cmpv
, newv
, tcg_constant_i32(oi
));
3479 TCGv_i128 oldv
= tcg_temp_new_i128();
3480 TCGv_i128 tmpv
= tcg_temp_new_i128();
3481 TCGv_i64 t0
= tcg_temp_new_i64();
3482 TCGv_i64 t1
= tcg_temp_new_i64();
3483 TCGv_i64 z
= tcg_constant_i64(0);
3485 tcg_gen_qemu_ld_i128(oldv
, addr
, idx
, memop
);
3488 tcg_gen_xor_i64(t0
, TCGV128_LOW(oldv
), TCGV128_LOW(cmpv
));
3489 tcg_gen_xor_i64(t1
, TCGV128_HIGH(oldv
), TCGV128_HIGH(cmpv
));
3490 tcg_gen_or_i64(t0
, t0
, t1
);
3492 /* tmpv = equal ? newv : oldv */
3493 tcg_gen_movcond_i64(TCG_COND_EQ
, TCGV128_LOW(tmpv
), t0
, z
,
3494 TCGV128_LOW(newv
), TCGV128_LOW(oldv
));
3495 tcg_gen_movcond_i64(TCG_COND_EQ
, TCGV128_HIGH(tmpv
), t0
, z
,
3496 TCGV128_HIGH(newv
), TCGV128_HIGH(oldv
));
3498 /* Unconditional writeback. */
3499 tcg_gen_qemu_st_i128(tmpv
, addr
, idx
, memop
);
3500 tcg_gen_mov_i128(retv
, oldv
);
3502 tcg_temp_free_i64(t0
);
3503 tcg_temp_free_i64(t1
);
3504 tcg_temp_free_i128(tmpv
);
3505 tcg_temp_free_i128(oldv
);
3509 void tcg_gen_atomic_cmpxchg_i128(TCGv_i128 retv
, TCGv addr
, TCGv_i128 cmpv
,
3510 TCGv_i128 newv
, TCGArg idx
, MemOp memop
)
3512 gen_atomic_cx_i128 gen
;
3514 if (!(tcg_ctx
->gen_tb
->cflags
& CF_PARALLEL
)) {
3515 tcg_gen_nonatomic_cmpxchg_i128(retv
, addr
, cmpv
, newv
, idx
, memop
);
3519 tcg_debug_assert((memop
& MO_SIZE
) == MO_128
);
3520 tcg_debug_assert((memop
& MO_SIGN
) == 0);
3521 gen
= table_cmpxchg
[memop
& (MO_SIZE
| MO_BSWAP
)];
3524 MemOpIdx oi
= make_memop_idx(memop
, idx
);
3525 gen(retv
, cpu_env
, addr
, cmpv
, newv
, tcg_constant_i32(oi
));
3529 gen_helper_exit_atomic(cpu_env
);
3532 * Produce a result for a well-formed opcode stream. This satisfies
3533 * liveness for set before used, which happens before this dead code
3536 tcg_gen_movi_i64(TCGV128_LOW(retv
), 0);
3537 tcg_gen_movi_i64(TCGV128_HIGH(retv
), 0);
3540 static void do_nonatomic_op_i32(TCGv_i32 ret
, TCGv addr
, TCGv_i32 val
,
3541 TCGArg idx
, MemOp memop
, bool new_val
,
3542 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
))
3544 TCGv_i32 t1
= tcg_temp_new_i32();
3545 TCGv_i32 t2
= tcg_temp_new_i32();
3547 memop
= tcg_canonicalize_memop(memop
, 0, 0);
3549 tcg_gen_qemu_ld_i32(t1
, addr
, idx
, memop
);
3550 tcg_gen_ext_i32(t2
, val
, memop
);
3552 tcg_gen_qemu_st_i32(t2
, addr
, idx
, memop
);
3554 tcg_gen_ext_i32(ret
, (new_val
? t2
: t1
), memop
);
3555 tcg_temp_free_i32(t1
);
3556 tcg_temp_free_i32(t2
);
3559 static void do_atomic_op_i32(TCGv_i32 ret
, TCGv addr
, TCGv_i32 val
,
3560 TCGArg idx
, MemOp memop
, void * const table
[])
3562 gen_atomic_op_i32 gen
;
3565 memop
= tcg_canonicalize_memop(memop
, 0, 0);
3567 gen
= table
[memop
& (MO_SIZE
| MO_BSWAP
)];
3568 tcg_debug_assert(gen
!= NULL
);
3570 oi
= make_memop_idx(memop
& ~MO_SIGN
, idx
);
3571 gen(ret
, cpu_env
, addr
, val
, tcg_constant_i32(oi
));
3573 if (memop
& MO_SIGN
) {
3574 tcg_gen_ext_i32(ret
, ret
, memop
);
3578 static void do_nonatomic_op_i64(TCGv_i64 ret
, TCGv addr
, TCGv_i64 val
,
3579 TCGArg idx
, MemOp memop
, bool new_val
,
3580 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
))
3582 TCGv_i64 t1
= tcg_temp_new_i64();
3583 TCGv_i64 t2
= tcg_temp_new_i64();
3585 memop
= tcg_canonicalize_memop(memop
, 1, 0);
3587 tcg_gen_qemu_ld_i64(t1
, addr
, idx
, memop
);
3588 tcg_gen_ext_i64(t2
, val
, memop
);
3590 tcg_gen_qemu_st_i64(t2
, addr
, idx
, memop
);
3592 tcg_gen_ext_i64(ret
, (new_val
? t2
: t1
), memop
);
3593 tcg_temp_free_i64(t1
);
3594 tcg_temp_free_i64(t2
);
3597 static void do_atomic_op_i64(TCGv_i64 ret
, TCGv addr
, TCGv_i64 val
,
3598 TCGArg idx
, MemOp memop
, void * const table
[])
3600 memop
= tcg_canonicalize_memop(memop
, 1, 0);
3602 if ((memop
& MO_SIZE
) == MO_64
) {
3603 #ifdef CONFIG_ATOMIC64
3604 gen_atomic_op_i64 gen
;
3607 gen
= table
[memop
& (MO_SIZE
| MO_BSWAP
)];
3608 tcg_debug_assert(gen
!= NULL
);
3610 oi
= make_memop_idx(memop
& ~MO_SIGN
, idx
);
3611 gen(ret
, cpu_env
, addr
, val
, tcg_constant_i32(oi
));
3613 gen_helper_exit_atomic(cpu_env
);
3614 /* Produce a result, so that we have a well-formed opcode stream
3615 with respect to uses of the result in the (dead) code following. */
3616 tcg_gen_movi_i64(ret
, 0);
3617 #endif /* CONFIG_ATOMIC64 */
3619 TCGv_i32 v32
= tcg_temp_new_i32();
3620 TCGv_i32 r32
= tcg_temp_new_i32();
3622 tcg_gen_extrl_i64_i32(v32
, val
);
3623 do_atomic_op_i32(r32
, addr
, v32
, idx
, memop
& ~MO_SIGN
, table
);
3624 tcg_temp_free_i32(v32
);
3626 tcg_gen_extu_i32_i64(ret
, r32
);
3627 tcg_temp_free_i32(r32
);
3629 if (memop
& MO_SIGN
) {
3630 tcg_gen_ext_i64(ret
, ret
, memop
);
3635 #define GEN_ATOMIC_HELPER(NAME, OP, NEW) \
3636 static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = { \
3637 [MO_8] = gen_helper_atomic_##NAME##b, \
3638 [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le, \
3639 [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be, \
3640 [MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le, \
3641 [MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be, \
3642 WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le) \
3643 WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be) \
3645 void tcg_gen_atomic_##NAME##_i32 \
3646 (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop) \
3648 if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \
3649 do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \
3651 do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \
3652 tcg_gen_##OP##_i32); \
3655 void tcg_gen_atomic_##NAME##_i64 \
3656 (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop) \
3658 if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \
3659 do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \
3661 do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \
3662 tcg_gen_##OP##_i64); \
3666 GEN_ATOMIC_HELPER(fetch_add
, add
, 0)
3667 GEN_ATOMIC_HELPER(fetch_and
, and, 0)
3668 GEN_ATOMIC_HELPER(fetch_or
, or, 0)
3669 GEN_ATOMIC_HELPER(fetch_xor
, xor, 0)
3670 GEN_ATOMIC_HELPER(fetch_smin
, smin
, 0)
3671 GEN_ATOMIC_HELPER(fetch_umin
, umin
, 0)
3672 GEN_ATOMIC_HELPER(fetch_smax
, smax
, 0)
3673 GEN_ATOMIC_HELPER(fetch_umax
, umax
, 0)
3675 GEN_ATOMIC_HELPER(add_fetch
, add
, 1)
3676 GEN_ATOMIC_HELPER(and_fetch
, and, 1)
3677 GEN_ATOMIC_HELPER(or_fetch
, or, 1)
3678 GEN_ATOMIC_HELPER(xor_fetch
, xor, 1)
3679 GEN_ATOMIC_HELPER(smin_fetch
, smin
, 1)
3680 GEN_ATOMIC_HELPER(umin_fetch
, umin
, 1)
3681 GEN_ATOMIC_HELPER(smax_fetch
, smax
, 1)
3682 GEN_ATOMIC_HELPER(umax_fetch
, umax
, 1)
3684 static void tcg_gen_mov2_i32(TCGv_i32 r
, TCGv_i32 a
, TCGv_i32 b
)
3686 tcg_gen_mov_i32(r
, b
);
3689 static void tcg_gen_mov2_i64(TCGv_i64 r
, TCGv_i64 a
, TCGv_i64 b
)
3691 tcg_gen_mov_i64(r
, b
);
3694 GEN_ATOMIC_HELPER(xchg
, mov2
, 0)
3696 #undef GEN_ATOMIC_HELPER