Revision a7812ae4 tcg/tcg.c
b/tcg/tcg.c | ||
---|---|---|
267 | 267 |
tcg_abort(); |
268 | 268 |
} |
269 | 269 |
|
270 |
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name) |
|
270 |
static inline int tcg_global_reg_new_internal(TCGType type, int reg, |
|
271 |
const char *name) |
|
271 | 272 |
{ |
272 | 273 |
TCGContext *s = &tcg_ctx; |
273 | 274 |
TCGTemp *ts; |
... | ... | |
289 | 290 |
ts->name = name; |
290 | 291 |
s->nb_globals++; |
291 | 292 |
tcg_regset_set_reg(s->reserved_regs, reg); |
292 |
return MAKE_TCGV(idx); |
|
293 |
return idx; |
|
294 |
} |
|
295 |
|
|
296 |
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name) |
|
297 |
{ |
|
298 |
int idx; |
|
299 |
|
|
300 |
idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name); |
|
301 |
return MAKE_TCGV_I32(idx); |
|
302 |
} |
|
303 |
|
|
304 |
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name) |
|
305 |
{ |
|
306 |
int idx; |
|
307 |
|
|
308 |
idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name); |
|
309 |
return MAKE_TCGV_I64(idx); |
|
293 | 310 |
} |
294 | 311 |
|
295 | 312 |
#if TCG_TARGET_REG_BITS == 32 |
296 | 313 |
/* temporary hack to avoid register shortage for tcg_qemu_st64() */ |
297 |
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
|
|
298 |
const char *name) |
|
314 |
TCGv_i64 tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
|
|
315 |
const char *name)
|
|
299 | 316 |
{ |
300 | 317 |
TCGContext *s = &tcg_ctx; |
301 | 318 |
TCGTemp *ts; |
... | ... | |
325 | 342 |
ts->name = strdup(buf); |
326 | 343 |
|
327 | 344 |
s->nb_globals += 2; |
328 |
return MAKE_TCGV(idx); |
|
345 |
return MAKE_TCGV_I64(idx);
|
|
329 | 346 |
} |
330 | 347 |
#endif |
331 | 348 |
|
332 |
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset, |
|
333 |
const char *name) |
|
349 |
static inline int tcg_global_mem_new_internal(TCGType type, int reg, |
|
350 |
tcg_target_long offset, |
|
351 |
const char *name) |
|
334 | 352 |
{ |
335 | 353 |
TCGContext *s = &tcg_ctx; |
336 | 354 |
TCGTemp *ts; |
... | ... | |
386 | 404 |
ts->name = name; |
387 | 405 |
s->nb_globals++; |
388 | 406 |
} |
389 |
return MAKE_TCGV(idx); |
|
407 |
return idx; |
|
408 |
} |
|
409 |
|
|
410 |
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset, |
|
411 |
const char *name) |
|
412 |
{ |
|
413 |
int idx; |
|
414 |
|
|
415 |
idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name); |
|
416 |
return MAKE_TCGV_I32(idx); |
|
417 |
} |
|
418 |
|
|
419 |
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset, |
|
420 |
const char *name) |
|
421 |
{ |
|
422 |
int idx; |
|
423 |
|
|
424 |
idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name); |
|
425 |
return MAKE_TCGV_I64(idx); |
|
390 | 426 |
} |
391 | 427 |
|
392 |
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
|
|
428 |
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
|
|
393 | 429 |
{ |
394 | 430 |
TCGContext *s = &tcg_ctx; |
395 | 431 |
TCGTemp *ts; |
... | ... | |
437 | 473 |
s->nb_temps++; |
438 | 474 |
} |
439 | 475 |
} |
440 |
return MAKE_TCGV(idx);
|
|
476 |
return idx;
|
|
441 | 477 |
} |
442 | 478 |
|
443 |
void tcg_temp_free(TCGv arg) |
|
479 |
TCGv_i32 tcg_temp_new_internal_i32(int temp_local) |
|
480 |
{ |
|
481 |
int idx; |
|
482 |
|
|
483 |
idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local); |
|
484 |
return MAKE_TCGV_I32(idx); |
|
485 |
} |
|
486 |
|
|
487 |
TCGv_i64 tcg_temp_new_internal_i64(int temp_local) |
|
488 |
{ |
|
489 |
int idx; |
|
490 |
|
|
491 |
idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local); |
|
492 |
return MAKE_TCGV_I64(idx); |
|
493 |
} |
|
494 |
|
|
495 |
static inline void tcg_temp_free_internal(int idx) |
|
444 | 496 |
{ |
445 | 497 |
TCGContext *s = &tcg_ctx; |
446 | 498 |
TCGTemp *ts; |
447 |
int idx = GET_TCGV(arg); |
|
448 | 499 |
int k; |
449 | 500 |
|
450 | 501 |
assert(idx >= s->nb_globals && idx < s->nb_temps); |
... | ... | |
458 | 509 |
s->first_free_temp[k] = idx; |
459 | 510 |
} |
460 | 511 |
|
512 |
void tcg_temp_free_i32(TCGv_i32 arg) |
|
513 |
{ |
|
514 |
tcg_temp_free_internal(GET_TCGV_I32(arg)); |
|
515 |
} |
|
516 |
|
|
517 |
void tcg_temp_free_i64(TCGv_i64 arg) |
|
518 |
{ |
|
519 |
tcg_temp_free_internal(GET_TCGV_I64(arg)); |
|
520 |
} |
|
461 | 521 |
|
462 |
TCGv tcg_const_i32(int32_t val) |
|
522 |
TCGv_i32 tcg_const_i32(int32_t val)
|
|
463 | 523 |
{ |
464 |
TCGv t0; |
|
465 |
t0 = tcg_temp_new(TCG_TYPE_I32);
|
|
524 |
TCGv_i32 t0;
|
|
525 |
t0 = tcg_temp_new_i32();
|
|
466 | 526 |
tcg_gen_movi_i32(t0, val); |
467 | 527 |
return t0; |
468 | 528 |
} |
469 | 529 |
|
470 |
TCGv tcg_const_i64(int64_t val) |
|
530 |
TCGv_i64 tcg_const_i64(int64_t val)
|
|
471 | 531 |
{ |
472 |
TCGv t0; |
|
473 |
t0 = tcg_temp_new(TCG_TYPE_I64);
|
|
532 |
TCGv_i64 t0;
|
|
533 |
t0 = tcg_temp_new_i64();
|
|
474 | 534 |
tcg_gen_movi_i64(t0, val); |
475 | 535 |
return t0; |
476 | 536 |
} |
477 | 537 |
|
478 |
TCGv tcg_const_local_i32(int32_t val) |
|
538 |
TCGv_i32 tcg_const_local_i32(int32_t val)
|
|
479 | 539 |
{ |
480 |
TCGv t0; |
|
481 |
t0 = tcg_temp_local_new(TCG_TYPE_I32);
|
|
540 |
TCGv_i32 t0;
|
|
541 |
t0 = tcg_temp_local_new_i32();
|
|
482 | 542 |
tcg_gen_movi_i32(t0, val); |
483 | 543 |
return t0; |
484 | 544 |
} |
485 | 545 |
|
486 |
TCGv tcg_const_local_i64(int64_t val) |
|
546 |
TCGv_i64 tcg_const_local_i64(int64_t val)
|
|
487 | 547 |
{ |
488 |
TCGv t0; |
|
489 |
t0 = tcg_temp_local_new(TCG_TYPE_I64);
|
|
548 |
TCGv_i64 t0;
|
|
549 |
t0 = tcg_temp_local_new_i64();
|
|
490 | 550 |
tcg_gen_movi_i64(t0, val); |
491 | 551 |
return t0; |
492 | 552 |
} |
... | ... | |
510 | 570 |
s->nb_helpers++; |
511 | 571 |
} |
512 | 572 |
|
513 |
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg) |
|
514 |
{ |
|
515 |
return s->temps[GET_TCGV(arg)].base_type; |
|
516 |
} |
|
517 |
|
|
518 |
static void tcg_gen_call_internal(TCGContext *s, TCGv func, |
|
519 |
unsigned int flags, |
|
520 |
unsigned int nb_rets, const TCGv *rets, |
|
521 |
unsigned int nb_params, const TCGv *params) |
|
522 |
{ |
|
523 |
int i; |
|
524 |
*gen_opc_ptr++ = INDEX_op_call; |
|
525 |
*gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1); |
|
526 |
for(i = 0; i < nb_rets; i++) { |
|
527 |
*gen_opparam_ptr++ = GET_TCGV(rets[i]); |
|
528 |
} |
|
529 |
for(i = 0; i < nb_params; i++) { |
|
530 |
*gen_opparam_ptr++ = GET_TCGV(params[i]); |
|
531 |
} |
|
532 |
*gen_opparam_ptr++ = GET_TCGV(func); |
|
533 |
|
|
534 |
*gen_opparam_ptr++ = flags; |
|
535 |
/* total parameters, needed to go backward in the instruction stream */ |
|
536 |
*gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3; |
|
537 |
} |
|
538 |
|
|
539 |
|
|
540 |
#if TCG_TARGET_REG_BITS < 64 |
|
541 | 573 |
/* Note: we convert the 64 bit args to 32 bit and do some alignment |
542 | 574 |
and endian swap. Maybe it would be better to do the alignment |
543 | 575 |
and endian swap in tcg_reg_alloc_call(). */ |
544 |
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, |
|
545 |
unsigned int nb_rets, const TCGv *rets, |
|
546 |
unsigned int nb_params, const TCGv *args1) |
|
576 |
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, |
|
577 |
int sizemask, TCGArg ret, int nargs, TCGArg *args) |
|
547 | 578 |
{ |
548 |
TCGv ret, *args2, rets_2[2], arg; |
|
549 |
int j, i, call_type; |
|
550 |
|
|
551 |
if (nb_rets == 1) { |
|
552 |
ret = rets[0]; |
|
553 |
if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) { |
|
554 |
nb_rets = 2; |
|
579 |
int call_type; |
|
580 |
int i; |
|
581 |
int real_args; |
|
582 |
int nb_rets; |
|
583 |
TCGArg *nparam; |
|
584 |
*gen_opc_ptr++ = INDEX_op_call; |
|
585 |
nparam = gen_opparam_ptr++; |
|
586 |
call_type = (flags & TCG_CALL_TYPE_MASK); |
|
587 |
if (ret != TCG_CALL_DUMMY_ARG) { |
|
588 |
#if TCG_TARGET_REG_BITS < 64 |
|
589 |
if (sizemask & 1) { |
|
555 | 590 |
#ifdef TCG_TARGET_WORDS_BIGENDIAN |
556 |
rets_2[0] = TCGV_HIGH(ret);
|
|
557 |
rets_2[1] = ret;
|
|
591 |
*gen_opparam_ptr++ = ret + 1;
|
|
592 |
*gen_opparam_ptr++ = ret;
|
|
558 | 593 |
#else |
559 |
rets_2[0] = ret;
|
|
560 |
rets_2[1] = TCGV_HIGH(ret);
|
|
594 |
*gen_opparam_ptr++ = ret;
|
|
595 |
*gen_opparam_ptr++ = ret + 1;
|
|
561 | 596 |
#endif |
562 |
rets = rets_2; |
|
597 |
nb_rets = 2; |
|
598 |
} else |
|
599 |
#endif |
|
600 |
{ |
|
601 |
*gen_opparam_ptr++ = ret; |
|
602 |
nb_rets = 1; |
|
563 | 603 |
} |
604 |
} else { |
|
605 |
nb_rets = 0; |
|
564 | 606 |
} |
565 |
args2 = alloca((nb_params * 3) * sizeof(TCGv)); |
|
566 |
j = 0; |
|
567 |
call_type = (flags & TCG_CALL_TYPE_MASK); |
|
568 |
for(i = 0; i < nb_params; i++) { |
|
569 |
arg = args1[i]; |
|
570 |
if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) { |
|
607 |
real_args = 0; |
|
608 |
for (i = 0; i < nargs; i++) { |
|
609 |
#if TCG_TARGET_REG_BITS < 64 |
|
610 |
if (sizemask & (2 << i)) { |
|
571 | 611 |
#ifdef TCG_TARGET_I386 |
572 | 612 |
/* REGPARM case: if the third parameter is 64 bit, it is |
573 | 613 |
allocated on the stack */ |
574 |
if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
|
|
614 |
if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
|
|
575 | 615 |
call_type = TCG_CALL_TYPE_REGPARM_2; |
576 | 616 |
flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type; |
577 | 617 |
} |
578 |
args2[j++] = arg; |
|
579 |
args2[j++] = TCGV_HIGH(arg); |
|
580 |
#else |
|
618 |
#endif |
|
581 | 619 |
#ifdef TCG_TARGET_CALL_ALIGN_ARGS |
582 | 620 |
/* some targets want aligned 64 bit args */ |
583 |
if (j & 1) {
|
|
584 |
args2[j++] = TCG_CALL_DUMMY_ARG;
|
|
621 |
if (i & 1) {
|
|
622 |
*gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
|
|
585 | 623 |
} |
586 | 624 |
#endif |
587 | 625 |
#ifdef TCG_TARGET_WORDS_BIGENDIAN |
588 |
args2[j++] = TCGV_HIGH(arg);
|
|
589 |
args2[j++] = arg;
|
|
626 |
*gen_opparam_ptr++ = args[i] + 1;
|
|
627 |
*gen_opparam_ptr++ = args[i];
|
|
590 | 628 |
#else |
591 |
args2[j++] = arg;
|
|
592 |
args2[j++] = TCGV_HIGH(arg);
|
|
629 |
*gen_opparam_ptr++ = args[i];
|
|
630 |
*gen_opparam_ptr++ = args[i] + 1;
|
|
593 | 631 |
#endif |
632 |
real_args += 2; |
|
633 |
} else |
|
594 | 634 |
#endif |
595 |
} else { |
|
596 |
args2[j++] = arg; |
|
635 |
{ |
|
636 |
*gen_opparam_ptr++ = args[i]; |
|
637 |
real_args++; |
|
597 | 638 |
} |
598 | 639 |
} |
599 |
tcg_gen_call_internal(s, func, flags, |
|
600 |
nb_rets, rets, j, args2); |
|
601 |
} |
|
602 |
#else |
|
603 |
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, |
|
604 |
unsigned int nb_rets, const TCGv *rets, |
|
605 |
unsigned int nb_params, const TCGv *args1) |
|
606 |
{ |
|
607 |
tcg_gen_call_internal(s, func, flags, |
|
608 |
nb_rets, rets, nb_params, args1); |
|
640 |
*gen_opparam_ptr++ = GET_TCGV_PTR(func); |
|
641 |
|
|
642 |
*gen_opparam_ptr++ = flags; |
|
643 |
|
|
644 |
*nparam = (nb_rets << 16) | (real_args + 1); |
|
645 |
|
|
646 |
/* total parameters, needed to go backward in the instruction stream */ |
|
647 |
*gen_opparam_ptr++ = 1 + nb_rets + real_args + 3; |
|
609 | 648 |
} |
610 |
#endif |
|
611 | 649 |
|
612 | 650 |
#if TCG_TARGET_REG_BITS == 32 |
613 |
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
|
|
651 |
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
|
|
614 | 652 |
int c, int right, int arith) |
615 | 653 |
{ |
616 | 654 |
if (c == 0) { |
617 |
tcg_gen_mov_i32(ret, arg1);
|
|
655 |
tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
|
|
618 | 656 |
tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); |
619 | 657 |
} else if (c >= 32) { |
620 | 658 |
c -= 32; |
621 | 659 |
if (right) { |
622 | 660 |
if (arith) { |
623 |
tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
|
|
661 |
tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
|
|
624 | 662 |
tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); |
625 | 663 |
} else { |
626 |
tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
|
|
664 |
tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
|
|
627 | 665 |
tcg_gen_movi_i32(TCGV_HIGH(ret), 0); |
628 | 666 |
} |
629 | 667 |
} else { |
630 |
tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
|
|
631 |
tcg_gen_movi_i32(ret, 0);
|
|
668 |
tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
|
|
669 |
tcg_gen_movi_i32(TCGV_LOW(ret), 0);
|
|
632 | 670 |
} |
633 | 671 |
} else { |
634 |
TCGv t0, t1; |
|
672 |
TCGv_i32 t0, t1;
|
|
635 | 673 |
|
636 |
t0 = tcg_temp_new(TCG_TYPE_I32);
|
|
637 |
t1 = tcg_temp_new(TCG_TYPE_I32);
|
|
674 |
t0 = tcg_temp_new_i32();
|
|
675 |
t1 = tcg_temp_new_i32();
|
|
638 | 676 |
if (right) { |
639 | 677 |
tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c); |
640 | 678 |
if (arith) |
641 | 679 |
tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c); |
642 |
else
|
|
680 |
else |
|
643 | 681 |
tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c); |
644 |
tcg_gen_shri_i32(ret, arg1, c);
|
|
645 |
tcg_gen_or_i32(ret, ret, t0);
|
|
682 |
tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
|
|
683 |
tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
|
|
646 | 684 |
tcg_gen_mov_i32(TCGV_HIGH(ret), t1); |
647 | 685 |
} else { |
648 |
tcg_gen_shri_i32(t0, arg1, 32 - c);
|
|
686 |
tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
|
|
649 | 687 |
/* Note: ret can be the same as arg1, so we use t1 */ |
650 |
tcg_gen_shli_i32(t1, arg1, c);
|
|
688 |
tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
|
|
651 | 689 |
tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); |
652 | 690 |
tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0); |
653 |
tcg_gen_mov_i32(ret, t1);
|
|
691 |
tcg_gen_mov_i32(TCGV_LOW(ret), t1);
|
|
654 | 692 |
} |
655 |
tcg_temp_free(t0); |
|
656 |
tcg_temp_free(t1); |
|
693 |
tcg_temp_free_i32(t0);
|
|
694 |
tcg_temp_free_i32(t1);
|
|
657 | 695 |
} |
658 | 696 |
} |
659 | 697 |
#endif |
... | ... | |
698 | 736 |
return buf; |
699 | 737 |
} |
700 | 738 |
|
701 |
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg) |
|
739 |
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg) |
|
740 |
{ |
|
741 |
return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg)); |
|
742 |
} |
|
743 |
|
|
744 |
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg) |
|
702 | 745 |
{ |
703 |
return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg)); |
|
746 |
return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
|
|
704 | 747 |
} |
705 | 748 |
|
706 | 749 |
static int helper_cmp(const void *p1, const void *p2) |
Also available in: Unified diff