audio: make playback packet length calculation exact
[qemu/ar7.git] / tcg / tcg-op.c
blobf2269a1b9135e821134c9e03fc7cae4fe7e06501
1 /*
2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "exec/exec-all.h"
27 #include "tcg/tcg.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);
37 op->args[0] = a1;
40 void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
42 TCGOp *op = tcg_emit_op(opc, 2);
43 op->args[0] = a1;
44 op->args[1] = a2;
47 void tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
49 TCGOp *op = tcg_emit_op(opc, 3);
50 op->args[0] = a1;
51 op->args[1] = a2;
52 op->args[2] = a3;
55 void tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
57 TCGOp *op = tcg_emit_op(opc, 4);
58 op->args[0] = a1;
59 op->args[1] = a2;
60 op->args[2] = a3;
61 op->args[3] = a4;
64 void tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
65 TCGArg a4, TCGArg a5)
67 TCGOp *op = tcg_emit_op(opc, 5);
68 op->args[0] = a1;
69 op->args[1] = a2;
70 op->args[2] = a3;
71 op->args[3] = a4;
72 op->args[4] = a5;
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);
79 op->args[0] = a1;
80 op->args[1] = a2;
81 op->args[2] = a3;
82 op->args[3] = a4;
83 op->args[4] = a5;
84 op->args[5] = a6;
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);
94 /* 32 bit ops */
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 */
104 if (arg2 == 0) {
105 tcg_gen_mov_i32(ret, arg1);
106 } else {
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);
116 } else {
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 */
124 if (arg2 == 0) {
125 tcg_gen_mov_i32(ret, arg1);
126 } else {
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. */
134 switch (arg2) {
135 case 0:
136 tcg_gen_movi_i32(ret, 0);
137 return;
138 case -1:
139 tcg_gen_mov_i32(ret, arg1);
140 return;
141 case 0xff:
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);
145 return;
147 break;
148 case 0xffff:
149 if (TCG_TARGET_HAS_ext16u_i32) {
150 tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
151 return;
153 break;
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. */
162 if (arg2 == -1) {
163 tcg_gen_movi_i32(ret, -1);
164 } else if (arg2 == 0) {
165 tcg_gen_mov_i32(ret, arg1);
166 } else {
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. */
174 if (arg2 == 0) {
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);
179 } else {
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);
187 if (arg2 == 0) {
188 tcg_gen_mov_i32(ret, arg1);
189 } else {
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);
197 if (arg2 == 0) {
198 tcg_gen_mov_i32(ret, arg1);
199 } else {
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);
207 if (arg2 == 0) {
208 tcg_gen_mov_i32(ret, arg1);
209 } else {
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) {
217 tcg_gen_br(l);
218 } else if (cond != TCG_COND_NEVER) {
219 l->refs++;
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) {
227 tcg_gen_br(l);
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);
240 } else {
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)
253 if (arg2 == 0) {
254 tcg_gen_movi_i32(ret, 0);
255 } else if (is_power_of_2(arg2)) {
256 tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
257 } else {
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_ebb_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);
271 } else {
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_ebb_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_ebb_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);
291 } else {
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_ebb_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);
305 } else {
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_ebb_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_ebb_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);
325 } else {
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);
334 } else {
335 TCGv_i32 t0 = tcg_temp_ebb_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);
346 } else {
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);
356 } else {
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);
366 } else {
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);
376 } else {
377 TCGv_i32 t0 = tcg_temp_ebb_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_ebb_new_i64();
390 TCGv_i64 t2 = tcg_temp_ebb_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);
399 } else {
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_ebb_new_i64();
415 TCGv_i64 t2 = tcg_temp_ebb_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_ebb_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);
432 } else {
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);
442 } else {
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_ebb_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);
456 } else {
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_ebb_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);
470 } else {
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_ebb_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);
485 } else {
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);
494 } else {
495 TCGv_i32 t0, t1;
497 t0 = tcg_temp_ebb_new_i32();
498 t1 = tcg_temp_ebb_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 */
512 if (arg2 == 0) {
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));
516 } else {
517 TCGv_i32 t0, t1;
518 t0 = tcg_temp_ebb_new_i32();
519 t1 = tcg_temp_ebb_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);
532 } else {
533 TCGv_i32 t0, t1;
535 t0 = tcg_temp_ebb_new_i32();
536 t1 = tcg_temp_ebb_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 */
550 if (arg2 == 0) {
551 tcg_gen_mov_i32(ret, arg1);
552 } else {
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)
560 uint32_t mask;
561 TCGv_i32 t1;
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);
568 if (len == 32) {
569 tcg_gen_mov_i32(ret, arg2);
570 return;
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);
574 return;
577 t1 = tcg_temp_ebb_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);
583 goto done;
585 if (ofs == 0) {
586 tcg_gen_extract2_i32(ret, arg1, arg2, len);
587 tcg_gen_rotli_i32(ret, ret, len);
588 goto done;
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);
596 } else {
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);
601 done:
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);
621 } else {
622 /* To help two-operand hosts we prefer to zero-extend first,
623 which allows ARG to stay live. */
624 switch (len) {
625 case 16:
626 if (TCG_TARGET_HAS_ext16u_i32) {
627 tcg_gen_ext16u_i32(ret, arg);
628 tcg_gen_shli_i32(ret, ret, ofs);
629 return;
631 break;
632 case 8:
633 if (TCG_TARGET_HAS_ext8u_i32) {
634 tcg_gen_ext8u_i32(ret, arg);
635 tcg_gen_shli_i32(ret, ret, ofs);
636 return;
638 break;
640 /* Otherwise prefer zero-extension over AND for code size. */
641 switch (ofs + len) {
642 case 16:
643 if (TCG_TARGET_HAS_ext16u_i32) {
644 tcg_gen_shli_i32(ret, arg, ofs);
645 tcg_gen_ext16u_i32(ret, ret);
646 return;
648 break;
649 case 8:
650 if (TCG_TARGET_HAS_ext8u_i32) {
651 tcg_gen_shli_i32(ret, arg, ofs);
652 tcg_gen_ext8u_i32(ret, ret);
653 return;
655 break;
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);
673 return;
675 if (ofs == 0) {
676 tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
677 return;
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);
683 return;
686 /* Assume that zero-extension, if available, is cheaper than a shift. */
687 switch (ofs + len) {
688 case 16:
689 if (TCG_TARGET_HAS_ext16u_i32) {
690 tcg_gen_ext16u_i32(ret, arg);
691 tcg_gen_shri_i32(ret, ret, ofs);
692 return;
694 break;
695 case 8:
696 if (TCG_TARGET_HAS_ext8u_i32) {
697 tcg_gen_ext8u_i32(ret, arg);
698 tcg_gen_shri_i32(ret, ret, ofs);
699 return;
701 break;
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. */
707 switch (len) {
708 case 1 ... 8: case 16:
709 tcg_gen_shri_i32(ret, arg, ofs);
710 tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
711 break;
712 default:
713 tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
714 tcg_gen_shri_i32(ret, ret, 32 - len);
715 break;
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);
730 return;
732 if (ofs == 0) {
733 switch (len) {
734 case 16:
735 tcg_gen_ext16s_i32(ret, arg);
736 return;
737 case 8:
738 tcg_gen_ext8s_i32(ret, arg);
739 return;
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);
746 return;
749 /* Assume that sign-extension, if available, is cheaper than a shift. */
750 switch (ofs + len) {
751 case 16:
752 if (TCG_TARGET_HAS_ext16s_i32) {
753 tcg_gen_ext16s_i32(ret, arg);
754 tcg_gen_sari_i32(ret, ret, ofs);
755 return;
757 break;
758 case 8:
759 if (TCG_TARGET_HAS_ext8s_i32) {
760 tcg_gen_ext8s_i32(ret, arg);
761 tcg_gen_sari_i32(ret, ret, ofs);
762 return;
764 break;
766 switch (len) {
767 case 16:
768 if (TCG_TARGET_HAS_ext16s_i32) {
769 tcg_gen_shri_i32(ret, arg, ofs);
770 tcg_gen_ext16s_i32(ret, ret);
771 return;
773 break;
774 case 8:
775 if (TCG_TARGET_HAS_ext8s_i32) {
776 tcg_gen_shri_i32(ret, arg, ofs);
777 tcg_gen_ext8s_i32(ret, ret);
778 return;
780 break;
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,
792 unsigned int ofs)
794 tcg_debug_assert(ofs <= 32);
795 if (ofs == 0) {
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);
803 } else {
804 TCGv_i32 t0 = tcg_temp_ebb_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);
820 } else {
821 TCGv_i32 t0 = tcg_temp_ebb_new_i32();
822 TCGv_i32 t1 = tcg_temp_ebb_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);
838 } else {
839 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
840 TCGv_i64 t1 = tcg_temp_ebb_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);
855 } else {
856 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
857 TCGv_i64 t1 = tcg_temp_ebb_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_ebb_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_ebb_new_i64();
879 TCGv_i64 t1 = tcg_temp_ebb_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);
886 } else {
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_ebb_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_ebb_new_i32();
903 TCGv_i32 t1 = tcg_temp_ebb_new_i32();
904 TCGv_i32 t2 = tcg_temp_ebb_new_i32();
905 TCGv_i32 t3 = tcg_temp_ebb_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);
919 } else {
920 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
921 TCGv_i64 t1 = tcg_temp_ebb_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_ebb_new_i32();
935 TCGv_i32 t1 = tcg_temp_ebb_new_i32();
936 TCGv_i32 t2 = tcg_temp_ebb_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);
946 } else {
947 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
948 TCGv_i64 t1 = tcg_temp_ebb_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);
962 } else {
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);
972 } else {
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);
982 } else {
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);
991 } else {
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);
1003 } else {
1004 TCGv_i32 t0 = tcg_temp_ebb_new_i32();
1005 TCGv_i32 t1 = tcg_temp_ebb_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);
1018 } else {
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);
1032 } else {
1033 TCGv_i32 t0 = tcg_temp_ebb_new_i32();
1034 TCGv_i32 t1 = tcg_temp_ebb_new_i32();
1035 TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
1037 /* arg = abcd */
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_ebb_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);
1089 /* 64-bit ops */
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);
1107 } else {
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 */
1159 #if HOST_BIG_ENDIAN
1160 tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
1161 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
1162 #else
1163 tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
1164 tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
1165 #endif
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)
1185 #if HOST_BIG_ENDIAN
1186 tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
1187 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
1188 #else
1189 tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
1190 tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
1191 #endif
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)
1241 TCGv_i64 t0;
1242 TCGv_i32 t1;
1244 t0 = tcg_temp_ebb_new_i64();
1245 t1 = tcg_temp_ebb_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);
1260 #else
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 */
1272 if (arg2 == 0) {
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));
1276 } else {
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);
1290 } else {
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 */
1300 if (arg2 == 0) {
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));
1304 } else {
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);
1316 return;
1319 /* Some cases can be optimized here. */
1320 switch (arg2) {
1321 case 0:
1322 tcg_gen_movi_i64(ret, 0);
1323 return;
1324 case -1:
1325 tcg_gen_mov_i64(ret, arg1);
1326 return;
1327 case 0xff:
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);
1331 return;
1333 break;
1334 case 0xffff:
1335 if (TCG_TARGET_HAS_ext16u_i64) {
1336 tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
1337 return;
1339 break;
1340 case 0xffffffffu:
1341 if (TCG_TARGET_HAS_ext32u_i64) {
1342 tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
1343 return;
1345 break;
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);
1356 return;
1358 /* Some cases can be optimized here. */
1359 if (arg2 == -1) {
1360 tcg_gen_movi_i64(ret, -1);
1361 } else if (arg2 == 0) {
1362 tcg_gen_mov_i64(ret, arg1);
1363 } else {
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);
1373 return;
1375 /* Some cases can be optimized here. */
1376 if (arg2 == 0) {
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);
1381 } else {
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);
1390 if (c == 0) {
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) {
1394 c -= 32;
1395 if (right) {
1396 if (arith) {
1397 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1398 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
1399 } else {
1400 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
1401 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
1403 } else {
1404 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
1405 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
1407 } else if (right) {
1408 if (TCG_TARGET_HAS_extract2_i32) {
1409 tcg_gen_extract2_i32(TCGV_LOW(ret),
1410 TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
1411 } else {
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);
1416 if (arith) {
1417 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1418 } else {
1419 tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
1421 } else {
1422 if (TCG_TARGET_HAS_extract2_i32) {
1423 tcg_gen_extract2_i32(TCGV_HIGH(ret),
1424 TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
1425 } else {
1426 TCGv_i32 t0 = tcg_temp_ebb_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);
1443 } else {
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);
1455 } else {
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);
1467 } else {
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) {
1475 tcg_gen_br(l);
1476 } else if (cond != TCG_COND_NEVER) {
1477 l->refs++;
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));
1482 } else {
1483 tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond,
1484 label_arg(l));
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) {
1494 tcg_gen_br(l);
1495 } else if (cond != TCG_COND_NEVER) {
1496 l->refs++;
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);
1512 } else {
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);
1518 } else {
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);
1533 } else {
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)
1544 if (arg2 == 0) {
1545 tcg_gen_movi_i64(ret, 0);
1546 } else if (is_power_of_2(arg2)) {
1547 tcg_gen_shli_i64(ret, arg1, ctz64(arg2));
1548 } else {
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_ebb_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);
1564 } else {
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_ebb_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_ebb_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);
1584 } else {
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_ebb_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);
1598 } else {
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_ebb_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_ebb_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);
1618 } else {
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);
1630 } else {
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);
1643 } else {
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);
1656 } else {
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);
1669 } else {
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);
1681 } else {
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);
1693 } else {
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);
1707 } else {
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);
1712 } else {
1713 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1714 TCGv_i64 t1 = tcg_temp_ebb_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);
1727 } else {
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);
1746 } else {
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);
1751 } else {
1752 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1753 TCGv_i64 t1 = tcg_temp_ebb_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.. */
1767 } else {
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) {
1780 TCGv_i32 t0, t1;
1781 t0 = tcg_temp_ebb_new_i32();
1782 t1 = tcg_temp_ebb_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);
1792 } else {
1793 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
1794 TCGv_i64 t1 = tcg_temp_ebb_new_i64();
1795 TCGv_i64 t2 = tcg_temp_ebb_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_ebb_new_i64();
1826 TCGv_i64 t1 = tcg_temp_ebb_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);
1853 } else {
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);
1865 } else {
1866 TCGv_i64 t0 = tcg_temp_ebb_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);
1880 } else {
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);
1893 } else {
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);
1906 } else {
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);
1919 } else {
1920 TCGv_i64 t0 = tcg_temp_ebb_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);
1931 } else {
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_ebb_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);
1947 } else {
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_ebb_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);
1965 } else {
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);
1976 } else {
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_ebb_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
1994 && arg2 == 64) {
1995 /* This equivalence has the advantage of not requiring a fixup. */
1996 TCGv_i64 t = tcg_temp_ebb_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);
2001 } else {
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_ebb_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);
2017 } else {
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);
2031 } else {
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);
2040 } else {
2041 TCGv_i64 t0, t1;
2042 t0 = tcg_temp_ebb_new_i64();
2043 t1 = tcg_temp_ebb_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 */
2057 if (arg2 == 0) {
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));
2061 } else {
2062 TCGv_i64 t0, t1;
2063 t0 = tcg_temp_ebb_new_i64();
2064 t1 = tcg_temp_ebb_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);
2077 } else {
2078 TCGv_i64 t0, t1;
2079 t0 = tcg_temp_ebb_new_i64();
2080 t1 = tcg_temp_ebb_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 */
2094 if (arg2 == 0) {
2095 tcg_gen_mov_i64(ret, arg1);
2096 } else {
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)
2104 uint64_t mask;
2105 TCGv_i64 t1;
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);
2112 if (len == 64) {
2113 tcg_gen_mov_i64(ret, arg2);
2114 return;
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);
2118 return;
2121 if (TCG_TARGET_REG_BITS == 32) {
2122 if (ofs >= 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));
2126 return;
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));
2132 return;
2136 t1 = tcg_temp_ebb_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);
2142 goto done;
2144 if (ofs == 0) {
2145 tcg_gen_extract2_i64(ret, arg1, arg2, len);
2146 tcg_gen_rotli_i64(ret, ret, len);
2147 goto done;
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);
2155 } else {
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);
2160 done:
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);
2180 } else {
2181 if (TCG_TARGET_REG_BITS == 32) {
2182 if (ofs >= 32) {
2183 tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg),
2184 ofs - 32, len);
2185 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
2186 return;
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);
2191 return;
2194 /* To help two-operand hosts we prefer to zero-extend first,
2195 which allows ARG to stay live. */
2196 switch (len) {
2197 case 32:
2198 if (TCG_TARGET_HAS_ext32u_i64) {
2199 tcg_gen_ext32u_i64(ret, arg);
2200 tcg_gen_shli_i64(ret, ret, ofs);
2201 return;
2203 break;
2204 case 16:
2205 if (TCG_TARGET_HAS_ext16u_i64) {
2206 tcg_gen_ext16u_i64(ret, arg);
2207 tcg_gen_shli_i64(ret, ret, ofs);
2208 return;
2210 break;
2211 case 8:
2212 if (TCG_TARGET_HAS_ext8u_i64) {
2213 tcg_gen_ext8u_i64(ret, arg);
2214 tcg_gen_shli_i64(ret, ret, ofs);
2215 return;
2217 break;
2219 /* Otherwise prefer zero-extension over AND for code size. */
2220 switch (ofs + len) {
2221 case 32:
2222 if (TCG_TARGET_HAS_ext32u_i64) {
2223 tcg_gen_shli_i64(ret, arg, ofs);
2224 tcg_gen_ext32u_i64(ret, ret);
2225 return;
2227 break;
2228 case 16:
2229 if (TCG_TARGET_HAS_ext16u_i64) {
2230 tcg_gen_shli_i64(ret, arg, ofs);
2231 tcg_gen_ext16u_i64(ret, ret);
2232 return;
2234 break;
2235 case 8:
2236 if (TCG_TARGET_HAS_ext8u_i64) {
2237 tcg_gen_shli_i64(ret, arg, ofs);
2238 tcg_gen_ext8u_i64(ret, ret);
2239 return;
2241 break;
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);
2259 return;
2261 if (ofs == 0) {
2262 tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
2263 return;
2266 if (TCG_TARGET_REG_BITS == 32) {
2267 /* Look for a 32-bit extract within one of the two words. */
2268 if (ofs >= 32) {
2269 tcg_gen_extract_i32(TCGV_LOW(ret), TCGV_HIGH(arg), ofs - 32, len);
2270 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
2271 return;
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);
2276 return;
2278 /* The field is split across two words. One double-word
2279 shift is better than two double-word shifts. */
2280 goto do_shift_and;
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);
2286 return;
2289 /* Assume that zero-extension, if available, is cheaper than a shift. */
2290 switch (ofs + len) {
2291 case 32:
2292 if (TCG_TARGET_HAS_ext32u_i64) {
2293 tcg_gen_ext32u_i64(ret, arg);
2294 tcg_gen_shri_i64(ret, ret, ofs);
2295 return;
2297 break;
2298 case 16:
2299 if (TCG_TARGET_HAS_ext16u_i64) {
2300 tcg_gen_ext16u_i64(ret, arg);
2301 tcg_gen_shri_i64(ret, ret, ofs);
2302 return;
2304 break;
2305 case 8:
2306 if (TCG_TARGET_HAS_ext8u_i64) {
2307 tcg_gen_ext8u_i64(ret, arg);
2308 tcg_gen_shri_i64(ret, ret, ofs);
2309 return;
2311 break;
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. */
2317 switch (len) {
2318 case 1 ... 8: case 16: case 32:
2319 do_shift_and:
2320 tcg_gen_shri_i64(ret, arg, ofs);
2321 tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
2322 break;
2323 default:
2324 tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
2325 tcg_gen_shri_i64(ret, ret, 64 - len);
2326 break;
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);
2341 return;
2343 if (ofs == 0) {
2344 switch (len) {
2345 case 32:
2346 tcg_gen_ext32s_i64(ret, arg);
2347 return;
2348 case 16:
2349 tcg_gen_ext16s_i64(ret, arg);
2350 return;
2351 case 8:
2352 tcg_gen_ext8s_i64(ret, arg);
2353 return;
2357 if (TCG_TARGET_REG_BITS == 32) {
2358 /* Look for a 32-bit extract within one of the two words. */
2359 if (ofs >= 32) {
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);
2366 return;
2367 } else if (len > 32) {
2368 TCGv_i32 t = tcg_temp_ebb_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);
2376 return;
2377 } else {
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);
2386 return;
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);
2392 return;
2395 /* Assume that sign-extension, if available, is cheaper than a shift. */
2396 switch (ofs + len) {
2397 case 32:
2398 if (TCG_TARGET_HAS_ext32s_i64) {
2399 tcg_gen_ext32s_i64(ret, arg);
2400 tcg_gen_sari_i64(ret, ret, ofs);
2401 return;
2403 break;
2404 case 16:
2405 if (TCG_TARGET_HAS_ext16s_i64) {
2406 tcg_gen_ext16s_i64(ret, arg);
2407 tcg_gen_sari_i64(ret, ret, ofs);
2408 return;
2410 break;
2411 case 8:
2412 if (TCG_TARGET_HAS_ext8s_i64) {
2413 tcg_gen_ext8s_i64(ret, arg);
2414 tcg_gen_sari_i64(ret, ret, ofs);
2415 return;
2417 break;
2419 switch (len) {
2420 case 32:
2421 if (TCG_TARGET_HAS_ext32s_i64) {
2422 tcg_gen_shri_i64(ret, arg, ofs);
2423 tcg_gen_ext32s_i64(ret, ret);
2424 return;
2426 break;
2427 case 16:
2428 if (TCG_TARGET_HAS_ext16s_i64) {
2429 tcg_gen_shri_i64(ret, arg, ofs);
2430 tcg_gen_ext16s_i64(ret, ret);
2431 return;
2433 break;
2434 case 8:
2435 if (TCG_TARGET_HAS_ext8s_i64) {
2436 tcg_gen_shri_i64(ret, arg, ofs);
2437 tcg_gen_ext8s_i64(ret, ret);
2438 return;
2440 break;
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,
2451 unsigned int ofs)
2453 tcg_debug_assert(ofs <= 64);
2454 if (ofs == 0) {
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);
2462 } else {
2463 TCGv_i64 t0 = tcg_temp_ebb_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_ebb_new_i32();
2479 TCGv_i32 t1 = tcg_temp_ebb_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));
2490 } else {
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);
2505 } else {
2506 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2507 TCGv_i64 t1 = tcg_temp_ebb_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);
2523 } else {
2524 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2525 TCGv_i64 t1 = tcg_temp_ebb_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);
2541 } else {
2542 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
2543 TCGv_i64 t1 = tcg_temp_ebb_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_ebb_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);
2564 } else {
2565 TCGv_i64 t0 = tcg_temp_ebb_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_ebb_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_ebb_new_i64();
2585 TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2586 TCGv_i64 t2 = tcg_temp_ebb_new_i64();
2587 TCGv_i64 t3 = tcg_temp_ebb_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);
2601 } else {
2602 TCGv_i64 t0 = tcg_temp_ebb_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_ebb_new_i64();
2613 TCGv_i64 t1 = tcg_temp_ebb_new_i64();
2614 TCGv_i64 t2 = tcg_temp_ebb_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_ebb_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));
2665 } else {
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));
2677 } else {
2678 TCGv_i64 t = tcg_temp_ebb_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);
2690 } else {
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);
2701 } else {
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)
2709 TCGv_i64 tmp;
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);
2714 return;
2717 tmp = tcg_temp_ebb_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);
2726 } else {
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));
2738 } else {
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)
2764 if (dst != 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;
2787 if (tb == NULL) {
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));
2794 #endif
2795 } else {
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;
2814 #endif
2815 plugin_gen_disable_mem_helpers();
2816 tcg_gen_op1i(INDEX_op_goto_tb, idx);
2819 void tcg_gen_lookup_and_goto_ptr(void)
2821 TCGv_ptr ptr;
2823 if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) {
2824 tcg_gen_exit_tb(NULL, 0);
2825 return;
2828 plugin_gen_disable_mem_helpers();
2829 ptr = tcg_temp_ebb_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) {
2846 case MO_8:
2847 op &= ~MO_BSWAP;
2848 break;
2849 case MO_16:
2850 break;
2851 case MO_32:
2852 if (!is64) {
2853 op &= ~MO_SIGN;
2855 break;
2856 case MO_64:
2857 if (is64) {
2858 op &= ~MO_SIGN;
2859 break;
2861 /* fall through */
2862 default:
2863 g_assert_not_reached();
2865 if (st) {
2866 op &= ~MO_SIGN;
2868 return op;
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);
2877 #else
2878 if (TCG_TARGET_REG_BITS == 32) {
2879 tcg_gen_op4i_i32(opc, val, TCGV_LOW(addr), TCGV_HIGH(addr), oi);
2880 } else {
2881 tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_i64_arg(addr), oi);
2883 #endif
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);
2893 } else {
2894 tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_i32_arg(addr), oi);
2896 #else
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);
2900 } else {
2901 tcg_gen_op3i_i64(opc, val, addr, oi);
2903 #endif
2906 static void tcg_gen_req_mo(TCGBar type)
2908 #ifdef TCG_GUEST_DEFAULT_MO
2909 type &= TCG_GUEST_DEFAULT_MO;
2910 #endif
2911 type &= ~TCG_TARGET_DEFAULT_MO;
2912 if (type) {
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);
2924 return temp;
2926 #endif
2927 return 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);
2939 #endif
2942 void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
2944 MemOp orig_memop;
2945 MemOpIdx oi;
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);
2951 orig_memop = memop;
2952 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
2953 memop &= ~MO_BSWAP;
2954 /* The bswap primitive benefits from zero-extended input. */
2955 if ((memop & MO_SSIZE) == MO_SW) {
2956 memop &= ~MO_SIGN;
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) {
2966 case MO_16:
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));
2970 break;
2971 case MO_32:
2972 tcg_gen_bswap32_i32(val, val);
2973 break;
2974 default:
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;
2983 MemOpIdx oi;
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_ebb_new_i32();
2991 switch (memop & MO_SIZE) {
2992 case MO_16:
2993 tcg_gen_bswap16_i32(swap, val, 0);
2994 break;
2995 case MO_32:
2996 tcg_gen_bswap32_i32(swap, val);
2997 break;
2998 default:
2999 g_assert_not_reached();
3001 val = swap;
3002 memop &= ~MO_BSWAP;
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);
3008 } else {
3009 gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
3011 plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
3013 if (swap) {
3014 tcg_temp_free_i32(swap);
3018 void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
3020 MemOp orig_memop;
3021 MemOpIdx oi;
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);
3027 } else {
3028 tcg_gen_movi_i32(TCGV_HIGH(val), 0);
3030 return;
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);
3037 orig_memop = memop;
3038 if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
3039 memop &= ~MO_BSWAP;
3040 /* The bswap primitive benefits from zero-extended input. */
3041 if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
3042 memop &= ~MO_SIGN;
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) {
3055 case MO_16:
3056 tcg_gen_bswap16_i64(val, val, flags);
3057 break;
3058 case MO_32:
3059 tcg_gen_bswap32_i64(val, val, flags);
3060 break;
3061 case MO_64:
3062 tcg_gen_bswap64_i64(val, val);
3063 break;
3064 default:
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;
3073 MemOpIdx oi;
3075 if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
3076 tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
3077 return;
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_ebb_new_i64();
3086 switch (memop & MO_SIZE) {
3087 case MO_16:
3088 tcg_gen_bswap16_i64(swap, val, 0);
3089 break;
3090 case MO_32:
3091 tcg_gen_bswap32_i64(swap, val, 0);
3092 break;
3093 case MO_64:
3094 tcg_gen_bswap64_i64(swap, val);
3095 break;
3096 default:
3097 g_assert_not_reached();
3099 val = swap;
3100 memop &= ~MO_BSWAP;
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);
3107 if (swap) {
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)) {
3121 mop_1 &= ~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) {
3129 case MO_UNALN:
3130 case MO_ALIGN_2:
3131 case MO_ALIGN_4:
3132 mop_2 = mop_1;
3133 break;
3134 case MO_ALIGN_8:
3135 /* Prefer MO_ALIGN+MO_64 to MO_ALIGN_8+MO_64. */
3136 mop_1 = (mop_1 & ~MO_AMASK) | MO_ALIGN;
3137 mop_2 = mop_1;
3138 break;
3139 case MO_ALIGN:
3140 /* Second has 8-byte alignment; first has 16-byte alignment. */
3141 mop_2 = mop_1;
3142 mop_1 = (mop_1 & ~MO_AMASK) | MO_ALIGN_16;
3143 break;
3144 case MO_ALIGN_16:
3145 case MO_ALIGN_32:
3146 case MO_ALIGN_64:
3147 /* Second has 8-byte alignment; first retains original. */
3148 mop_2 = (mop_1 & ~MO_AMASK) | MO_ALIGN;
3149 break;
3150 default:
3151 g_assert_not_reached();
3153 ret[0] = mop_1;
3154 ret[1] = mop_2;
3157 void tcg_gen_qemu_ld_i128(TCGv_i128 val, TCGv addr, TCGArg idx, MemOp memop)
3159 MemOp mop[2];
3160 TCGv addr_p8;
3161 TCGv_i64 x, y;
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
3174 * subwords.
3176 if ((memop & MO_BSWAP) == MO_LE) {
3177 x = TCGV128_LOW(val);
3178 y = TCGV128_HIGH(val);
3179 } else {
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),
3200 QEMU_PLUGIN_MEM_R);
3203 void tcg_gen_qemu_st_i128(TCGv_i128 val, TCGv addr, TCGArg idx, MemOp memop)
3205 MemOp mop[2];
3206 TCGv addr_p8;
3207 TCGv_i64 x, y;
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);
3220 } else {
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_ebb_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);
3235 } else {
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),
3243 QEMU_PLUGIN_MEM_W);
3246 static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
3248 switch (opc & MO_SSIZE) {
3249 case MO_SB:
3250 tcg_gen_ext8s_i32(ret, val);
3251 break;
3252 case MO_UB:
3253 tcg_gen_ext8u_i32(ret, val);
3254 break;
3255 case MO_SW:
3256 tcg_gen_ext16s_i32(ret, val);
3257 break;
3258 case MO_UW:
3259 tcg_gen_ext16u_i32(ret, val);
3260 break;
3261 default:
3262 tcg_gen_mov_i32(ret, val);
3263 break;
3267 static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
3269 switch (opc & MO_SSIZE) {
3270 case MO_SB:
3271 tcg_gen_ext8s_i64(ret, val);
3272 break;
3273 case MO_UB:
3274 tcg_gen_ext8u_i64(ret, val);
3275 break;
3276 case MO_SW:
3277 tcg_gen_ext16s_i64(ret, val);
3278 break;
3279 case MO_UW:
3280 tcg_gen_ext16u_i64(ret, val);
3281 break;
3282 case MO_SL:
3283 tcg_gen_ext32s_i64(ret, val);
3284 break;
3285 case MO_UL:
3286 tcg_gen_ext32u_i64(ret, val);
3287 break;
3288 default:
3289 tcg_gen_mov_i64(ret, val);
3290 break;
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,
3307 #else
3308 # define WITH_ATOMIC64(X)
3309 #endif
3310 #ifdef CONFIG_CMPXCHG128
3311 # define WITH_ATOMIC128(X) X,
3312 #else
3313 # define WITH_ATOMIC128(X)
3314 #endif
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_ebb_new_i32();
3332 TCGv_i32 t2 = tcg_temp_ebb_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);
3343 } else {
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;
3353 MemOpIdx oi;
3355 if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
3356 tcg_gen_nonatomic_cmpxchg_i32(retv, addr, cmpv, newv, idx, memop);
3357 return;
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)
3375 TCGv_i64 t1, t2;
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);
3382 } else {
3383 tcg_gen_movi_i32(TCGV_HIGH(retv), 0);
3385 return;
3388 t1 = tcg_temp_ebb_new_i64();
3389 t2 = tcg_temp_ebb_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);
3400 } else {
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);
3411 return;
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)];
3419 if (gen) {
3420 MemOpIdx oi = make_memop_idx(memop, idx);
3421 gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3422 return;
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
3430 * is removed.
3432 tcg_gen_movi_i64(retv, 0);
3433 return;
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);
3441 } else {
3442 tcg_gen_movi_i32(TCGV_HIGH(retv), 0);
3444 } else {
3445 TCGv_i32 c32 = tcg_temp_ebb_new_i32();
3446 TCGv_i32 n32 = tcg_temp_ebb_new_i32();
3447 TCGv_i32 r32 = tcg_temp_ebb_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));
3478 } else {
3479 TCGv_i128 oldv = tcg_temp_ebb_new_i128();
3480 TCGv_i128 tmpv = tcg_temp_ebb_new_i128();
3481 TCGv_i64 t0 = tcg_temp_ebb_new_i64();
3482 TCGv_i64 t1 = tcg_temp_ebb_new_i64();
3483 TCGv_i64 z = tcg_constant_i64(0);
3485 tcg_gen_qemu_ld_i128(oldv, addr, idx, memop);
3487 /* Compare i128 */
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);
3516 return;
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)];
3523 if (gen) {
3524 MemOpIdx oi = make_memop_idx(memop, idx);
3525 gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
3526 return;
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
3534 * is removed.
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_ebb_new_i32();
3545 TCGv_i32 t2 = tcg_temp_ebb_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);
3551 gen(t2, t1, t2);
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;
3563 MemOpIdx oi;
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_ebb_new_i64();
3583 TCGv_i64 t2 = tcg_temp_ebb_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);
3589 gen(t2, t1, t2);
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;
3605 MemOpIdx oi;
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));
3612 #else
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 */
3618 } else {
3619 TCGv_i32 v32 = tcg_temp_ebb_new_i32();
3620 TCGv_i32 r32 = tcg_temp_ebb_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) \
3644 }; \
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); \
3650 } else { \
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); \
3660 } else { \
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