| @@ -527,16 +527,6 @@ void store(int r, SValue *v) · 526 unmodified lines |
| 527 | } | 527 | } |
| 528 | } | 528 | } |
| 529 | | 529 | |
| 530 | static void gadd_sp(int val) | | |
| 531 | { | | |
| 532 | if (val == (char)val) { | | |
| 533 | o(0xc48348); | | |
| 534 | g(val); | | |
| 535 | } else { | | |
| 536 | oad(0xc48148, val); /* add $xxx, %rsp */ | | |
| 537 | } | | |
| 538 | } | | |
| 539 | | | |
| 540 | /* 'is_jmp' is '1' if it is a jump */ | 530 | /* 'is_jmp' is '1' if it is a jump */ |
| 541 | static void gcall_or_jmp(int is_jmp) | 531 | static void gcall_or_jmp(int is_jmp) |
| 542 | { | 532 | { |
| @@ -564,16 +554,238 @@ static void gcall_or_jmp(int is_jmp) · 21 unmodified lines |
| 564 | } | 554 | } |
| 565 | | 555 | |
| 566 | #ifdef TCC_TARGET_PE | 556 | #ifdef TCC_TARGET_PE |
| | 557 | |
| 567 | #define REGN 4 | 558 | #define REGN 4 |
| 568 | static const uint8_t arg_regs[] = { | 559 | static const uint8_t arg_regs[] = { |
| 569 | TREG_RCX, TREG_RDX, TREG_R8, TREG_R9 | 560 | TREG_RCX, TREG_RDX, TREG_R8, TREG_R9 |
| 570 | }; | 561 | }; |
| | 562 | |
| | 563 | static int func_scratch; |
| | 564 | |
| | 565 | /* Generate function call. The function address is pushed first, then |
| | 566 | all the parameters in call order. This functions pops all the |
| | 567 | parameters and the function address. */ |
| | 568 | |
| | 569 | void gen_offs_sp(int b, int r, int d) |
| | 570 | { |
| | 571 | if (d == (char)d) { |
| | 572 | o(b | 0x4000 | (r << 11)); |
| | 573 | g(d); |
| | 574 | } else { |
| | 575 | o(b | 0x8000 | (r << 11)); |
| | 576 | gen_le32(d); |
| | 577 | } |
| | 578 | } |
| | 579 | |
| | 580 | void gfunc_call(int nb_args) |
| | 581 | { |
| | 582 | int size, align, r, args_size, i, d, j, bt; |
| | 583 | int nb_reg_args, gen_reg; |
| | 584 | |
| | 585 | /* calculate the number of integer/float arguments */ |
| | 586 | nb_reg_args = 0; |
| | 587 | for(i = 0; i < nb_args; i++) { |
| | 588 | bt = (vtop[-i].type.t & VT_BTYPE); |
| | 589 | if (bt != VT_STRUCT && bt != VT_LDOUBLE) |
| | 590 | nb_reg_args++; |
| | 591 | } |
| | 592 | |
| | 593 | args_size = (nb_reg_args < REGN ? REGN : nb_reg_args) * PTR_SIZE; |
| | 594 | save_regs(0); /* save used temporary registers */ |
| | 595 | |
| | 596 | /* for struct arguments, we need to call memcpy and the function |
| | 597 | call breaks register passing arguments we are preparing. |
| | 598 | So, we process arguments which will be passed by stack first. */ |
| | 599 | for(i = 0; i < nb_args; i++) { |
| | 600 | SValue *sv = &vtop[-i]; |
| | 601 | bt = (sv->type.t & VT_BTYPE); |
| | 602 | if (bt == VT_STRUCT) { |
| | 603 | size = type_size(&sv->type, &align); |
| | 604 | /* align to stack align size */ |
| | 605 | size = (size + 15) & ~16; |
| | 606 | /* generate structure store */ |
| | 607 | r = get_reg(RC_INT); |
| | 608 | o(0x48); |
| | 609 | gen_offs_sp(0x24048d, r, args_size); |
| | 610 | args_size += size; |
| | 611 | |
| | 612 | /* generate memcpy call */ |
| | 613 | vset(&sv->type, r | VT_LVAL, 0); |
| | 614 | *++vtop = *sv; |
| | 615 | vstore(); |
| | 616 | --vtop; |
| | 617 | |
| | 618 | } else if (bt == VT_LDOUBLE) { |
| | 619 | |
| | 620 | gv(RC_ST0); |
| | 621 | gen_offs_sp(0x243cdb, 0, args_size); |
| | 622 | args_size += 16; |
| | 623 | |
| | 624 | } |
| | 625 | } |
| | 626 | |
| | 627 | if (func_scratch < args_size) |
| | 628 | func_scratch = args_size; |
| | 629 | |
| | 630 | gen_reg = nb_reg_args; |
| | 631 | for(i = 0; i < nb_args; i++) { |
| | 632 | bt = (vtop->type.t & VT_BTYPE); |
| | 633 | if (bt == VT_STRUCT || bt == VT_LDOUBLE) { |
| | 634 | ; /* done */ |
| | 635 | |
| | 636 | } else if (is_sse_float(vtop->type.t)) { |
| | 637 | gv(RC_FLOAT); /* only one float register */ |
| | 638 | j = --gen_reg; |
| | 639 | if (j >= REGN) { |
| | 640 | o(0x0f66), |
| | 641 | /* movq %xmm0, j*8(%rsp) */ |
| | 642 | gen_offs_sp(0x2444d6, 0, j*8); |
| | 643 | } else { |
| | 644 | d = arg_regs[j]; |
| | 645 | /* movaps %xmm0, %xmmN */ |
| | 646 | o(0x280f); |
| | 647 | o(0xc0 + (j << 3)); |
| | 648 | /* mov %xmm0, %rxx */ |
| | 649 | o(0x66); |
| | 650 | o(0x7e0f48 + (d >= 8)); |
| | 651 | o(0xc0 + (d & 7)); |
| | 652 | } |
| | 653 | } else { |
| | 654 | r = gv(RC_INT); |
| | 655 | j = --gen_reg; |
| | 656 | if (j >= REGN) { |
| | 657 | o(0x48); |
| | 658 | gen_offs_sp(0x244489, r, j*8); |
| | 659 | } else { |
| | 660 | d = arg_regs[j]; |
| | 661 | if (d != r) { |
| | 662 | o(0x8948 + (d >= 8)); |
| | 663 | o(0xc0 + r*8 + (d & 7)); |
| | 664 | } |
| | 665 | } |
| | 666 | } |
| | 667 | vtop--; |
| | 668 | } |
| | 669 | gcall_or_jmp(0); |
| | 670 | vtop--; |
| | 671 | } |
| | 672 | |
| | 673 | |
| | 674 | #define FUNC_PROLOG_SIZE 11 |
| | 675 | |
| | 676 | /* generate function prolog of type 't' */ |
| | 677 | void gfunc_prolog(CType *func_type) |
| | 678 | { |
| | 679 | int addr, align, size, reg_param_index, bt; |
| | 680 | Sym *sym; |
| | 681 | CType *type; |
| | 682 | |
| | 683 | func_ret_sub = 0; |
| | 684 | func_scratch = 0; |
| | 685 | loc = 0; |
| | 686 | |
| | 687 | addr = PTR_SIZE * 2; |
| | 688 | ind += FUNC_PROLOG_SIZE; |
| | 689 | func_sub_sp_offset = ind; |
| | 690 | reg_param_index = 0; |
| | 691 | |
| | 692 | sym = func_type->ref; |
| | 693 | |
| | 694 | /* if the function returns a structure, then add an |
| | 695 | implicit pointer parameter */ |
| | 696 | func_vt = sym->type; |
| | 697 | if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
| | 698 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); |
| | 699 | reg_param_index++; |
| | 700 | addr += PTR_SIZE; |
| | 701 | } |
| | 702 | |
| | 703 | /* define parameters */ |
| | 704 | while ((sym = sym->next) != NULL) { |
| | 705 | type = &sym->type; |
| | 706 | bt = type->t & VT_BTYPE; |
| | 707 | if (bt == VT_STRUCT || bt == VT_LDOUBLE) |
| | 708 | continue; |
| | 709 | if (reg_param_index < REGN) { |
| | 710 | /* save arguments passed by register */ |
| | 711 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); |
| | 712 | } |
| | 713 | sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr); |
| | 714 | reg_param_index++; |
| | 715 | addr += PTR_SIZE; |
| | 716 | } |
| | 717 | |
| | 718 | while (reg_param_index < REGN) { |
| | 719 | if (func_type->ref->c == FUNC_ELLIPSIS) |
| | 720 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); |
| | 721 | reg_param_index++; |
| | 722 | addr += PTR_SIZE; |
| | 723 | } |
| | 724 | |
| | 725 | sym = func_type->ref; |
| | 726 | while ((sym = sym->next) != NULL) { |
| | 727 | type = &sym->type; |
| | 728 | bt = type->t & VT_BTYPE; |
| | 729 | if (bt == VT_STRUCT || bt == VT_LDOUBLE) { |
| | 730 | size = type_size(type, &align); |
| | 731 | size = (size + 15) & -16; |
| | 732 | sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr); |
| | 733 | addr += size; |
| | 734 | } |
| | 735 | } |
| | 736 | } |
| | 737 | |
| | 738 | /* generate function epilog */ |
| | 739 | void gfunc_epilog(void) |
| | 740 | { |
| | 741 | int v, saved_ind; |
| | 742 | |
| | 743 | o(0xc9); /* leave */ |
| | 744 | if (func_ret_sub == 0) { |
| | 745 | o(0xc3); /* ret */ |
| | 746 | } else { |
| | 747 | o(0xc2); /* ret n */ |
| | 748 | g(func_ret_sub); |
| | 749 | g(func_ret_sub >> 8); |
| | 750 | } |
| | 751 | |
| | 752 | saved_ind = ind; |
| | 753 | ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; |
| | 754 | /* align local size to word & save local variables */ |
| | 755 | v = (func_scratch + -loc + 15) & -16; |
| | 756 | |
| | 757 | pe_add_unwind_data(ind, saved_ind, v); |
| | 758 | |
| | 759 | if (v >= 4096) { |
| | 760 | Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); |
| | 761 | oad(0xb8, v); /* mov stacksize, %eax */ |
| | 762 | oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ |
| | 763 | greloc(cur_text_section, sym, ind-4, R_X86_64_PC32); |
| | 764 | o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */ |
| | 765 | } else { |
| | 766 | o(0xe5894855); /* push %rbp, mov %rsp, %rbp */ |
| | 767 | o(0xec8148); /* sub rsp, stacksize */ |
| | 768 | gen_le32(v); |
| | 769 | } |
| | 770 | ind = saved_ind; |
| | 771 | } |
| | 772 | |
| 571 | #else | 773 | #else |
| | 774 | |
| | 775 | static void gadd_sp(int val) |
| | 776 | { |
| | 777 | if (val == (char)val) { |
| | 778 | o(0xc48348); |
| | 779 | g(val); |
| | 780 | } else { |
| | 781 | oad(0xc48148, val); /* add $xxx, %rsp */ |
| | 782 | } |
| | 783 | } |
| | 784 | |
| 572 | #define REGN 6 | 785 | #define REGN 6 |
| 573 | static const uint8_t arg_regs[REGN] = { | 786 | static const uint8_t arg_regs[REGN] = { |
| 574 | TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9 | 787 | TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9 |
| 575 | }; | 788 | }; |
| 576 | #endif | | |
| 577 | | 789 | |
| 578 | /* Generate function call. The function address is pushed first, then | 790 | /* Generate function call. The function address is pushed first, then |
| 579 | all the parameters in call order. This functions pops all the | 791 | all the parameters in call order. This functions pops all the |
| @@ -593,11 +805,9 @@ void gfunc_call(int nb_args) · 13 unmodified lines |
| 593 | args_size += type_size(&vtop->type, &align); | 805 | args_size += type_size(&vtop->type, &align); |
| 594 | } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) { | 806 | } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) { |
| 595 | args_size += 16; | 807 | args_size += 16; |
| 596 | #ifndef TCC_TARGET_PE | | |
| 597 | } else if (is_sse_float(vtop[-i].type.t)) { | 808 | } else if (is_sse_float(vtop[-i].type.t)) { |
| 598 | nb_sse_args++; | 809 | nb_sse_args++; |
| 599 | if (nb_sse_args > 8) args_size += 8; | 810 | if (nb_sse_args > 8) args_size += 8; |
| 600 | #endif | | |
| 601 | } else { | 811 | } else { |
| 602 | nb_reg_args++; | 812 | nb_reg_args++; |
| 603 | if (nb_reg_args > REGN) args_size += 8; | 813 | if (nb_reg_args > REGN) args_size += 8; |
| @@ -611,10 +821,6 @@ void gfunc_call(int nb_args) · 7 unmodified lines |
| 611 | gen_reg = nb_reg_args; | 821 | gen_reg = nb_reg_args; |
| 612 | sse_reg = nb_sse_args; | 822 | sse_reg = nb_sse_args; |
| 613 | | 823 | |
| 614 | #ifdef TCC_TARGET_PE | | |
| 615 | save_regs(0); /* save used temporary registers */ | | |
| 616 | #endif | | |
| 617 | | | |
| 618 | /* adjust stack to align SSE boundary */ | 824 | /* adjust stack to align SSE boundary */ |
| 619 | if (args_size &= 8) { | 825 | if (args_size &= 8) { |
| 620 | o(0x50); /* push $rax */ | 826 | o(0x50); /* push $rax */ |
| @@ -650,13 +856,8 @@ void gfunc_call(int nb_args) · 29 unmodified lines |
| 650 | g(0x00); | 856 | g(0x00); |
| 651 | args_size += size; | 857 | args_size += size; |
| 652 | } else if (is_sse_float(vtop->type.t)) { | 858 | } else if (is_sse_float(vtop->type.t)) { |
| 653 | #ifdef TCC_TARGET_PE | | |
| 654 | int j = --gen_reg; | | |
| 655 | if (j >= REGN) { | | |
| 656 | #else | | |
| 657 | int j = --sse_reg; | 859 | int j = --sse_reg; |
| 658 | if (j >= 8) { | 860 | if (j >= 8) { |
| 659 | #endif | | |
| 660 | gv(RC_FLOAT); | 861 | gv(RC_FLOAT); |
| 661 | o(0x50); /* push $rax */ | 862 | o(0x50); /* push $rax */ |
| 662 | /* movq %xmm0, (%rsp) */ | 863 | /* movq %xmm0, (%rsp) */ |
| @@ -688,42 +889,6 @@ void gfunc_call(int nb_args) · 25 unmodified lines |
| 688 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT || | 889 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT || |
| 689 | (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { | 890 | (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { |
| 690 | } else if (is_sse_float(vtop->type.t)) { | 891 | } else if (is_sse_float(vtop->type.t)) { |
| 691 | #ifdef TCC_TARGET_PE | | |
| 692 | int j = --gen_reg; | | |
| 693 | if (j < REGN) { | | |
| 694 | int d = arg_regs[j]; | | |
| 695 | gv(RC_FLOAT); /* only one float register */ | | |
| 696 | /* movaps %xmm0, %xmmN */ | | |
| 697 | o(0x280f); | | |
| 698 | o(0xc0 + (j << 3)); | | |
| 699 | o(0x50); | | |
| 700 | o(0xd60f66); /* movq %xmm0, (%rsp) */ | | |
| 701 | o(0x2404 + (j << 3)); | | |
| 702 | if (d < 8) { | | |
| 703 | o(0x58 + d); /* pop d */ | | |
| 704 | } else { | | |
| 705 | o(0x58); | | |
| 706 | o(0xc08949 + d - 8); | | |
| 707 | } | | |
| 708 | } | | |
| 709 | } else { | | |
| 710 | int j = --gen_reg; | | |
| 711 | /* simple type */ | | |
| 712 | /* XXX: implicit cast ? */ | | |
| 713 | if (j < REGN) { | | |
| 714 | int d = arg_regs[j]; | | |
| 715 | r = gv(RC_INT); | | |
| 716 | if (d != r) { | | |
| 717 | if (d < 8) { | | |
| 718 | o(0x8948); /* mov */ | | |
| 719 | o(0xc0 + r * 8 + d); | | |
| 720 | } else { | | |
| 721 | o(0x8949); /* mov */ | | |
| 722 | o(0xc0 + r * 8 + d - 8); | | |
| 723 | } | | |
| 724 | } | | |
| 725 | } | | |
| 726 | #else | | |
| 727 | int j = --sse_reg; | 892 | int j = --sse_reg; |
| 728 | if (j < 8) { | 893 | if (j < 8) { |
| 729 | gv(RC_FLOAT); /* only one float register */ | 894 | gv(RC_FLOAT); /* only one float register */ |
| @@ -750,16 +915,10 @@ void gfunc_call(int nb_args) · 20 unmodified lines |
| 750 | o(0xc0 + r * 8 + j - 4); | 915 | o(0xc0 + r * 8 + j - 4); |
| 751 | } | 916 | } |
| 752 | } | 917 | } |
| 753 | #endif | | |
| 754 | } | 918 | } |
| 755 | vtop--; | 919 | vtop--; |
| 756 | } | 920 | } |
| 757 | | 921 | |
| 758 | #ifdef TCC_TARGET_PE | | |
| 759 | /* allocate scratch space */ | | |
| 760 | gadd_sp(-8*REGN); | | |
| 761 | args_size += 8*REGN; | | |
| 762 | #else | | |
| 763 | save_regs(0); /* save used temporary registers */ | 922 | save_regs(0); /* save used temporary registers */ |
| 764 | | 923 | |
| 765 | /* Copy R10 and R11 into RDX and RCX, respectively */ | 924 | /* Copy R10 and R11 into RDX and RCX, respectively */ |
| @@ -771,13 +930,13 @@ void gfunc_call(int nb_args) · 5 unmodified lines |
| 771 | } | 930 | } |
| 772 | | 931 | |
| 773 | oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */ | 932 | oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */ |
| 774 | #endif | | |
| 775 | gcall_or_jmp(0); | 933 | gcall_or_jmp(0); |
| 776 | if (args_size) | 934 | if (args_size) |
| 777 | gadd_sp(args_size); | 935 | gadd_sp(args_size); |
| 778 | vtop--; | 936 | vtop--; |
| 779 | } | 937 | } |
| 780 | | 938 | |
| | 939 | |
| 781 | #define FUNC_PROLOG_SIZE 11 | 940 | #define FUNC_PROLOG_SIZE 11 |
| 782 | | 941 | |
| 783 | static void push_arg_reg(int i) { | 942 | static void push_arg_reg(int i) { |
| @@ -793,15 +952,13 @@ void gfunc_prolog(CType *func_type) · 9 unmodified lines |
| 793 | Sym *sym; | 952 | Sym *sym; |
| 794 | CType *type; | 953 | CType *type; |
| 795 | | 954 | |
| 796 | func_ret_sub = 0; | | |
| 797 | | | |
| 798 | sym = func_type->ref; | 955 | sym = func_type->ref; |
| 799 | addr = PTR_SIZE * 2; | 956 | addr = PTR_SIZE * 2; |
| 800 | loc = 0; | 957 | loc = 0; |
| 801 | ind += FUNC_PROLOG_SIZE; | 958 | ind += FUNC_PROLOG_SIZE; |
| 802 | func_sub_sp_offset = ind; | 959 | func_sub_sp_offset = ind; |
| | 960 | func_ret_sub = 0; |
| 803 | | 961 | |
| 804 | #ifndef TCC_TARGET_PE | | |
| 805 | if (func_type->ref->c == FUNC_ELLIPSIS) { | 962 | if (func_type->ref->c == FUNC_ELLIPSIS) { |
| 806 | int seen_reg_num, seen_sse_num, seen_stack_size; | 963 | int seen_reg_num, seen_sse_num, seen_stack_size; |
| 807 | seen_reg_num = seen_sse_num = 0; | 964 | seen_reg_num = seen_sse_num = 0; |
| @@ -857,7 +1014,6 @@ void gfunc_prolog(CType *func_type) · 49 unmodified lines |
| 857 | push_arg_reg(REGN-1-i); | 1014 | push_arg_reg(REGN-1-i); |
| 858 | } | 1015 | } |
| 859 | } | 1016 | } |
| 860 | #endif | | |
| 861 | | 1017 | |
| 862 | sym = func_type->ref; | 1018 | sym = func_type->ref; |
| 863 | param_index = 0; | 1019 | param_index = 0; |
| @@ -880,7 +1036,6 @@ void gfunc_prolog(CType *func_type) · 16 unmodified lines |
| 880 | type = &sym->type; | 1036 | type = &sym->type; |
| 881 | size = type_size(type, &align); | 1037 | size = type_size(type, &align); |
| 882 | size = (size + 3) & ~3; | 1038 | size = (size + 3) & ~3; |
| 883 | #ifndef TCC_TARGET_PE | | |
| 884 | if (is_sse_float(type->t)) { | 1039 | if (is_sse_float(type->t)) { |
| 885 | if (sse_param_index < 8) { | 1040 | if (sse_param_index < 8) { |
| 886 | /* save arguments passed by register */ | 1041 | /* save arguments passed by register */ |
| @@ -893,21 +1048,12 @@ void gfunc_prolog(CType *func_type) · 6 unmodified lines |
| 893 | addr += size; | 1048 | addr += size; |
| 894 | } | 1049 | } |
| 895 | sse_param_index++; | 1050 | sse_param_index++; |
| 896 | } else | 1051 | |
| 897 | #endif | 1052 | } else if ((type->t & VT_BTYPE) == VT_STRUCT || |
| 898 | if ((type->t & VT_BTYPE) == VT_STRUCT || | | |
| 899 | (type->t & VT_BTYPE) == VT_LDOUBLE) { | 1053 | (type->t & VT_BTYPE) == VT_LDOUBLE) { |
| 900 | param_addr = addr; | 1054 | param_addr = addr; |
| 901 | addr += size; | 1055 | addr += size; |
| 902 | } else { | 1056 | } else { |
| 903 | #ifdef TCC_TARGET_PE | | |
| 904 | if (reg_param_index < REGN) { | | |
| 905 | /* save arguments passed by register */ | | |
| 906 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); | | |
| 907 | } | | |
| 908 | param_addr = addr; | | |
| 909 | addr += 8; | | |
| 910 | #else | | |
| 911 | if (reg_param_index < REGN) { | 1057 | if (reg_param_index < REGN) { |
| 912 | /* save arguments passed by register */ | 1058 | /* save arguments passed by register */ |
| 913 | push_arg_reg(reg_param_index); | 1059 | push_arg_reg(reg_param_index); |
| @@ -916,21 +1062,12 @@ void gfunc_prolog(CType *func_type) · 2 unmodified lines |
| 916 | param_addr = addr; | 1062 | param_addr = addr; |
| 917 | addr += 8; | 1063 | addr += 8; |
| 918 | } | 1064 | } |
| 919 | #endif | | |
| 920 | reg_param_index++; | 1065 | reg_param_index++; |
| 921 | } | 1066 | } |
| 922 | sym_push(sym->v & ~SYM_FIELD, type, | 1067 | sym_push(sym->v & ~SYM_FIELD, type, |
| 923 | VT_LOCAL | VT_LVAL, param_addr); | 1068 | VT_LOCAL | VT_LVAL, param_addr); |
| 924 | param_index++; | 1069 | param_index++; |
| 925 | } | 1070 | } |
| 926 | #ifdef TCC_TARGET_PE | | |
| 927 | if (func_type->ref->c == FUNC_ELLIPSIS) { | | |
| 928 | for (i = reg_param_index; i < REGN; ++i) { | | |
| 929 | gen_modrm64(0x89, arg_regs[i], VT_LOCAL, NULL, addr); | | |
| 930 | addr += 8; | | |
| 931 | } | | |
| 932 | } | | |
| 933 | #endif | | |
| 934 | } | 1071 | } |
| 935 | | 1072 | |
| 936 | /* generate function epilog */ | 1073 | /* generate function epilog */ |
| @@ -950,23 +1087,14 @@ void gfunc_epilog(void) · 13 unmodified lines |
| 950 | v = (-loc + 15) & -16; | 1087 | v = (-loc + 15) & -16; |
| 951 | saved_ind = ind; | 1088 | saved_ind = ind; |
| 952 | ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; | 1089 | ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; |
| 953 | #ifdef TCC_TARGET_PE | 1090 | o(0xe5894855); /* push %rbp, mov %rsp, %rbp */ |
| 954 | if (v >= 4096) { | 1091 | o(0xec8148); /* sub rsp, stacksize */ |
| 955 | Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); | 1092 | gen_le32(v); |
| 956 | oad(0xb8, v); /* mov stacksize, %eax */ | | |
| 957 | oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ | | |
| 958 | greloc(cur_text_section, sym, ind-4, R_X86_64_PC32); | | |
| 959 | o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */ | | |
| 960 | } else | | |
| 961 | #endif | | |
| 962 | { | | |
| 963 | o(0xe5894855); /* push %rbp, mov %rsp, %rbp */ | | |
| 964 | o(0xec8148); /* sub rsp, stacksize */ | | |
| 965 | gen_le32(v); | | |
| 966 | } | | |
| 967 | ind = saved_ind; | 1093 | ind = saved_ind; |
| 968 | } | 1094 | } |
| 969 | | 1095 | |
| | 1096 | #endif /* not PE */ |
| | 1097 | |
| 970 | /* generate a jump to a label */ | 1098 | /* generate a jump to a label */ |
| 971 | int gjmp(int t) | 1099 | int gjmp(int t) |
| 972 | { | 1100 | { |