Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27/arm-gen.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/tcc-0.9.27
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/tcc-0.9.27/arm-gen.c
r321 r331 1 1 /* 2 2 * ARMv4 code generator for TCC 3 * 3 * 4 4 * Copyright (c) 2003 Daniel Glöckner 5 5 * Copyright (c) 2012 Thomas Preud'homme … … 24 24 #ifdef TARGET_DEFS_ONLY 25 25 26 #ifdef TCC_ARM_EABI 27 #ifndef TCC_ARM_VFP // Avoid useless warning 28 #define TCC_ARM_VFP 29 #endif 26 #if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP) 27 #error "Currently TinyCC only supports float computation with VFP instructions" 30 28 #endif 31 29 … … 37 35 #endif 38 36 39 #ifndef TCC_ ARM_VERSION40 # define TCC_ ARM_VERSION 537 #ifndef TCC_CPU_VERSION 38 # define TCC_CPU_VERSION 5 41 39 #endif 42 40 … … 47 45 #define RC_FLOAT 0x0002 /* generic float register */ 48 46 #define RC_R0 0x0004 49 #define RC_R1 0x0008 47 #define RC_R1 0x0008 50 48 #define RC_R2 0x0010 51 49 #define RC_R3 0x0020 … … 82 80 TREG_F7, 83 81 #endif 82 TREG_SP = 13, 83 TREG_LR, 84 84 }; 85 85 … … 105 105 /* defined if structures are passed as pointers. Otherwise structures 106 106 are directly pushed on stack. */ 107 / /#define FUNC_STRUCT_PARAM_AS_PTR107 /* #define FUNC_STRUCT_PARAM_AS_PTR */ 108 108 109 109 /* pointer size, in bytes */ … … 131 131 132 132 /******************************************************/ 133 /* ELF defines */134 135 #define EM_TCC_TARGET EM_ARM136 137 /* relocation type for 32 bit data relocation */138 #define R_DATA_32 R_ARM_ABS32139 #define R_DATA_PTR R_ARM_ABS32140 #define R_JMP_SLOT R_ARM_JUMP_SLOT141 #define R_COPY R_ARM_COPY142 143 #define ELF_START_ADDR 0x00008000144 #define ELF_PAGE_SIZE 0x1000145 146 /******************************************************/147 133 #else /* ! TARGET_DEFS_ONLY */ 148 134 /******************************************************/ 149 135 #include "tcc.h" 136 137 enum float_abi float_abi; 150 138 151 139 ST_DATA const int reg_classes[NB_REGS] = { … … 172 160 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) 173 161 static CType float_type, double_type, func_float_type, func_double_type; 174 ST_FUNC void arm_init _types(void)162 ST_FUNC void arm_init(struct TCCState *s) 175 163 { 176 164 float_type.t = VT_FLOAT; … … 180 168 func_double_type.t = VT_FUNC; 181 169 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); 170 171 float_abi = s->float_abi; 172 #ifndef TCC_ARM_HARDFLOAT 173 tcc_warning("soft float ABI currently not supported: default to softfp"); 174 #endif 182 175 } 183 176 #else … … 185 178 #define func_double_type func_old_type 186 179 #define func_ldouble_type func_old_type 187 ST_FUNC void arm_init_types(void) {} 180 ST_FUNC void arm_init(struct TCCState *s) 181 { 182 #if 0 183 #if !defined (TCC_ARM_VFP) 184 tcc_warning("Support for FPA is deprecated and will be removed in next" 185 " release"); 186 #endif 187 #if !defined (TCC_ARM_EABI) 188 tcc_warning("Support for OABI is deprecated and will be removed in next" 189 " release"); 190 #endif 191 #endif 192 } 188 193 #endif 189 194 … … 198 203 /******************************************************/ 199 204 200 void o(unsigned int i) 205 #if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) 206 const char *default_elfinterp(struct TCCState *s) 207 { 208 if (s->float_abi == ARM_HARD_FLOAT) 209 return "/lib/ld-linux-armhf.so.3"; 210 else 211 return "/lib/ld-linux.so.3"; 212 } 213 #endif 214 215 void o(uint32_t i) 201 216 { 202 217 /* this is a good place to start adding big-endian support*/ 203 218 int ind1; 204 219 if (nocode_wanted) 220 return; 205 221 ind1 = ind + 4; 206 222 if (!cur_text_section) … … 212 228 i>>=8; 213 229 cur_text_section->data[ind++] = i&255; 214 i>>=8; 230 i>>=8; 215 231 cur_text_section->data[ind++] = i&255; 216 232 i>>=8; … … 328 344 } 329 345 330 ST_FUNCuint32_t encbranch(int pos, int addr, int fail)346 uint32_t encbranch(int pos, int addr, int fail) 331 347 { 332 348 addr-=pos+8; … … 377 393 if(r<TREG_F0 || r>TREG_F7) 378 394 tcc_error("compiler error! register %i is no vfp register",r); 379 return r -5;395 return r - TREG_F0; 380 396 } 381 397 #else … … 384 400 if(r<TREG_F0 || r>TREG_F3) 385 401 tcc_error("compiler error! register %i is no fpa register",r); 386 return r -5;402 return r - TREG_F0; 387 403 } 388 404 #endif … … 390 406 static uint32_t intr(int r) 391 407 { 392 if(r ==4)408 if(r == TREG_R12) 393 409 return 12; 394 if((r<0 || r>4) && r!=14) 395 tcc_error("compiler error! register %i is no int register",r); 396 return r; 410 if(r >= TREG_R0 && r <= TREG_R3) 411 return r - TREG_R0; 412 if (r >= TREG_SP && r <= TREG_LR) 413 return r + (13 - TREG_SP); 414 tcc_error("compiler error! register %i is no int register",r); 397 415 } 398 416 … … 499 517 fr = sv->r; 500 518 ft = sv->type.t; 501 fc = sv->c. ul;519 fc = sv->c.i; 502 520 503 521 if(fc>=0) … … 507 525 fc=-fc; 508 526 } 509 527 510 528 v = fr & VT_VALMASK; 511 529 if (fr & VT_LVAL) { … … 514 532 v1.type.t = VT_PTR; 515 533 v1.r = VT_LOCAL | VT_LVAL; 516 v1.c.ul = sv->c.ul; 517 load(base=14 /* lr */, &v1); 534 v1.c.i = sv->c.i; 535 load(TREG_LR, &v1); 536 base = 14; /* lr */ 518 537 fc=sign=0; 519 538 v=VT_LOCAL; … … 521 540 v1.type.t = VT_PTR; 522 541 v1.r = fr&~VT_LVAL; 523 v1.c. ul = sv->c.ul;542 v1.c.i = sv->c.i; 524 543 v1.sym=sv->sym; 525 load(base=14, &v1); 544 load(TREG_LR, &v1); 545 base = 14; /* lr */ 526 546 fc=sign=0; 527 547 v=VT_LOCAL; … … 572 592 if(!sign) 573 593 op|=0x800000; 574 if ((ft & VT_BTYPE) == VT_BYTE )594 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) 575 595 op|=0x400000; 576 596 o(op|(intr(r)<<12)|fc|(base<<16)); … … 580 600 } else { 581 601 if (v == VT_CONST) { 582 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c. ul);602 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i); 583 603 if (fr & VT_SYM || !op) { 584 604 o(0xE59F0000|(intr(r)<<12)); … … 586 606 if(fr & VT_SYM) 587 607 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); 588 o(sv->c. ul);608 o(sv->c.i); 589 609 } else 590 610 o(op); 591 611 return; 592 612 } else if (v == VT_LOCAL) { 593 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c. ul);613 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i); 594 614 if (fr & VT_SYM || !op) { 595 615 o(0xE59F0000|(intr(r)<<12)); … … 597 617 if(fr & VT_SYM) // needed ? 598 618 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); 599 o(sv->c. ul);619 o(sv->c.i); 600 620 o(0xE08B0000|(intr(r)<<12)|intr(r)); 601 621 } else … … 603 623 return; 604 624 } else if(v == VT_CMP) { 605 o(mapcc(sv->c. ul)|0x3A00001|(intr(r)<<12));606 o(mapcc(negcc(sv->c. ul))|0x3A00000|(intr(r)<<12));625 o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12)); 626 o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12)); 607 627 return; 608 628 } else if (v == VT_JMP || v == VT_JMPI) { … … 611 631 o(0xE3A00000|(intr(r)<<12)|t); 612 632 o(0xEA000000); 613 gsym(sv->c. ul);633 gsym(sv->c.i); 614 634 o(0xE3A00000|(intr(r)<<12)|(t^1)); 615 635 return; … … 638 658 fr = sv->r; 639 659 ft = sv->type.t; 640 fc = sv->c. ul;660 fc = sv->c.i; 641 661 642 662 if(fc>=0) … … 646 666 fc=-fc; 647 667 } 648 649 v = fr & VT_VALMASK; 668 669 v = fr & VT_VALMASK; 650 670 if (fr & VT_LVAL || fr == VT_LOCAL) { 651 uint32_t base = 0xb; 671 uint32_t base = 0xb; /* fp */ 652 672 if(v < VT_CONST) { 653 673 base=intr(v); … … 657 677 v1.type.t = ft; 658 678 v1.r = fr&~VT_LVAL; 659 v1.c. ul = sv->c.ul;679 v1.c.i = sv->c.i; 660 680 v1.sym=sv->sym; 661 load(base=14, &v1); 681 load(TREG_LR, &v1); 682 base = 14; /* lr */ 662 683 fc=sign=0; 663 v=VT_LOCAL; 684 v=VT_LOCAL; 664 685 } 665 686 if(v == VT_LOCAL) { … … 668 689 #ifdef TCC_ARM_VFP 669 690 op=0xED000A00; /* fsts */ 670 if(!sign) 671 op|=0x800000; 672 if ((ft & VT_BTYPE) != VT_FLOAT) 691 if(!sign) 692 op|=0x800000; 693 if ((ft & VT_BTYPE) != VT_FLOAT) 673 694 op|=0x100; /* fsts -> fstd */ 674 695 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); … … 700 721 if(!sign) 701 722 op|=0x800000; 702 if ((ft & VT_BTYPE) == VT_BYTE )723 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) 703 724 op|=0x400000; 704 725 o(op|(intr(r)<<12)|fc|(base<<16)); … … 722 743 uint32_t x; 723 744 /* constant case */ 724 x=encbranch(ind,ind+vtop->c. ul,0);745 x=encbranch(ind,ind+vtop->c.i,0); 725 746 if(x) { 726 747 if (vtop->r & VT_SYM) { … … 736 757 if (vtop->r & VT_SYM) 737 758 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); 738 o(vtop->c. ul);759 o(vtop->c.i); 739 760 } 740 761 } else { … … 747 768 } 748 769 749 #ifdef TCC_ARM_HARDFLOAT 750 static int is_float_hgen_aggr(CType *type) 770 static int unalias_ldbl(int btype) 771 { 772 #if LDOUBLE_SIZE == 8 773 if (btype == VT_LDOUBLE) 774 btype = VT_DOUBLE; 775 #endif 776 return btype; 777 } 778 779 /* Return whether a structure is an homogeneous float aggregate or not. 780 The answer is true if all the elements of the structure are of the same 781 primitive float type and there is less than 4 elements. 782 783 type: the type corresponding to the structure to be tested */ 784 static int is_hgen_float_aggr(CType *type) 751 785 { 752 786 if ((type->t & VT_BTYPE) == VT_STRUCT) { … … 754 788 int btype, nb_fields = 0; 755 789 756 ref = type->ref ;757 btype = ref->type.t & VT_BTYPE;790 ref = type->ref->next; 791 btype = unalias_ldbl(ref->type.t & VT_BTYPE); 758 792 if (btype == VT_FLOAT || btype == VT_DOUBLE) { 759 for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);793 for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); 760 794 return !ref && nb_fields <= 4; 761 795 } … … 765 799 766 800 struct avail_regs { 767 /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */ 768 signed char avail[3]; 769 int first_hole; 770 int last_hole; 771 int first_free_reg; 801 signed char avail[3]; /* 3 holes max with only float and double alignments */ 802 int first_hole; /* first available hole */ 803 int last_hole; /* last available hole (none if equal to first_hole) */ 804 int first_free_reg; /* next free register in the sequence, hole excluded */ 772 805 }; 773 806 774 807 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } 775 808 776 /* Assign a register for a CPRC param with correct size and alignment 777 * size and align are in bytes, as returned by type_size */ 778 int assign_fpreg(struct avail_regs *avregs, int align, int size) 809 /* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC 810 param) according to the rules described in the procedure call standard for 811 the ARM architecture (AAPCS). If found, the registers are assigned to this 812 VFP CPRC parameter. Registers are allocated in sequence unless a hole exists 813 and the parameter is a single float. 814 815 avregs: opaque structure to keep track of available VFP co-processor regs 816 align: alignment constraints for the param, as returned by type_size() 817 size: size of the parameter, as returned by type_size() */ 818 int assign_vfpreg(struct avail_regs *avregs, int align, int size) 779 819 { 780 820 int first_reg = 0; … … 782 822 if (avregs->first_free_reg == -1) 783 823 return -1; 784 if (align >> 3) { / / alignment needed (base type: double)824 if (align >> 3) { /* double alignment */ 785 825 first_reg = avregs->first_free_reg; 826 /* alignment constraint not respected so use next reg and record hole */ 786 827 if (first_reg & 1) 787 828 avregs->avail[avregs->last_hole++] = first_reg++; 788 } else { 829 } else { /* no special alignment (float or array of float) */ 830 /* if single float and a hole is available, assign the param to it */ 789 831 if (size == 4 && avregs->first_hole != avregs->last_hole) 790 832 return avregs->avail[avregs->first_hole++]; … … 799 841 return -1; 800 842 } 801 #endif 802 803 /* Generate function call. The function address is pushed first, then 804 all the parameters in call order. This functions pops all the 805 parameters and the function address. */ 806 void gfunc_call(int nb_args) 807 { 808 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno; 809 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}}; 810 SValue *before_stack = NULL; /* SValue before first on stack argument */ 811 SValue *before_vfpreg_hfa = NULL; /* SValue before first in VFP reg hfa argument */ 812 #ifdef TCC_ARM_HARDFLOAT 843 844 /* Returns whether all params need to be passed in core registers or not. 845 This is the case for function part of the runtime ABI. */ 846 int floats_in_core_regs(SValue *sval) 847 { 848 if (!sval->sym) 849 return 0; 850 851 switch (sval->sym->v) { 852 case TOK___floatundisf: 853 case TOK___floatundidf: 854 case TOK___fixunssfdi: 855 case TOK___fixunsdfdi: 856 #ifndef TCC_ARM_VFP 857 case TOK___fixunsxfdi: 858 #endif 859 case TOK___floatdisf: 860 case TOK___floatdidf: 861 case TOK___fixsfdi: 862 case TOK___fixdfdi: 863 return 1; 864 865 default: 866 return 0; 867 } 868 } 869 870 /* Return the number of registers needed to return the struct, or 0 if 871 returning via struct pointer. */ 872 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) { 873 #ifdef TCC_ARM_EABI 874 int size, align; 875 size = type_size(vt, &align); 876 if (float_abi == ARM_HARD_FLOAT && !variadic && 877 (is_float(vt->t) || is_hgen_float_aggr(vt))) { 878 *ret_align = 8; 879 *regsize = 8; 880 ret->ref = NULL; 881 ret->t = VT_DOUBLE; 882 return (size + 7) >> 3; 883 } else if (size <= 4) { 884 *ret_align = 4; 885 *regsize = 4; 886 ret->ref = NULL; 887 ret->t = VT_INT; 888 return 1; 889 } else 890 return 0; 891 #else 892 return 0; 893 #endif 894 } 895 896 /* Parameters are classified according to how they are copied to their final 897 destination for the function call. Because the copying is performed class 898 after class according to the order in the union below, it is important that 899 some constraints about the order of the members of this union are respected: 900 - CORE_STRUCT_CLASS must come after STACK_CLASS; 901 - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and 902 VFP_STRUCT_CLASS; 903 - VFP_STRUCT_CLASS must come after VFP_CLASS. 904 See the comment for the main loop in copy_params() for the reason. */ 905 enum reg_class { 906 STACK_CLASS = 0, 907 CORE_STRUCT_CLASS, 908 VFP_CLASS, 909 VFP_STRUCT_CLASS, 910 CORE_CLASS, 911 NB_CLASSES 912 }; 913 914 struct param_plan { 915 int start; /* first reg or addr used depending on the class */ 916 int end; /* last reg used or next free addr depending on the class */ 917 SValue *sval; /* pointer to SValue on the value stack */ 918 struct param_plan *prev; /* previous element in this class */ 919 }; 920 921 struct plan { 922 struct param_plan *pplans; /* array of all the param plans */ 923 struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */ 924 }; 925 926 #define add_param_plan(plan,pplan,class) \ 927 do { \ 928 pplan.prev = plan->clsplans[class]; \ 929 plan->pplans[plan ## _nb] = pplan; \ 930 plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \ 931 } while(0) 932 933 /* Assign parameters to registers and stack with alignment according to the 934 rules in the procedure call standard for the ARM architecture (AAPCS). 935 The overall assignment is recorded in an array of per parameter structures 936 called parameter plans. The parameter plans are also further organized in a 937 number of linked lists, one per class of parameter (see the comment for the 938 definition of union reg_class). 939 940 nb_args: number of parameters of the function for which a call is generated 941 float_abi: float ABI in use for this function call 942 plan: the structure where the overall assignment is recorded 943 todo: a bitmap that record which core registers hold a parameter 944 945 Returns the amount of stack space needed for parameter passing 946 947 Note: this function allocated an array in plan->pplans with tcc_malloc. It 948 is the responsibility of the caller to free this array once used (ie not 949 before copy_params). */ 950 static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) 951 { 952 int i, size, align; 953 int ncrn /* next core register number */, nsaa /* next stacked argument address*/; 954 int plan_nb = 0; 955 struct param_plan pplan; 813 956 struct avail_regs avregs = AVAIL_REGS_INITIALIZER; 814 signed char vfp_plan[16]; 815 int plan2[4+16]; 816 int variadic; 817 #else 818 int plan2[4]={0,0,0,0}; 819 #endif 820 int vfp_todo=0; 821 int todo=0, keep; 822 823 #ifdef TCC_ARM_HARDFLOAT 824 memset(vfp_plan, -1, sizeof(vfp_plan)); 825 memset(plan2, 0, sizeof(plan2)); 826 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); 827 #endif 828 r = vtop->r & VT_VALMASK; 829 if (r == VT_CMP || (r & ~1) == VT_JMP) 830 gv(RC_INT); 831 #ifdef TCC_ARM_EABI 832 if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT 833 && type_size(&vtop[-nb_args].type.ref->type, &align) <= 4) { 834 SValue tmp; 835 tmp=vtop[-nb_args]; 836 vtop[-nb_args]=vtop[-nb_args+1]; 837 vtop[-nb_args+1]=tmp; 838 --nb_args; 839 } 840 841 vpushi(0), nb_args++; 842 vtop->type.t = VT_LLONG; 843 #endif 844 ncrn = ncprn = argno = vfp_argno = args_size = 0; 845 /* Assign argument to registers and stack with alignment. 846 If, considering alignment constraints, enough registers of the correct type 847 (core or VFP) are free for the current argument, assign them to it, else 848 allocate on stack with correct alignment. Whenever a structure is allocated 849 in registers or on stack, it is always put on the stack at this stage. The 850 stack is divided in 3 zones. The zone are, from low addresses to high 851 addresses: structures to be loaded in core registers, structures to be 852 loaded in VFP registers, argument allocated to stack. SValue's representing 853 structures in the first zone are moved just after the SValue pointed by 854 before_vfpreg_hfa. SValue's representing structures in the second zone are 855 moved just after the SValue pointer by before_stack. */ 957 958 ncrn = nsaa = 0; 959 *todo = 0; 960 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); 961 memset(plan->clsplans, 0, sizeof(plan->clsplans)); 856 962 for(i = nb_args; i-- ;) { 857 int j, assigned_vfpreg = 0; 858 size = type_size(&vtop[-i].type, &align); 963 int j, start_vfpreg = 0; 964 CType type = vtop[-i].type; 965 type.t &= ~VT_ARRAY; 966 size = type_size(&type, &align); 967 size = (size + 3) & ~3; 968 align = (align + 3) & ~3; 859 969 switch(vtop[-i].type.t & VT_BTYPE) { 860 970 case VT_STRUCT: … … 862 972 case VT_DOUBLE: 863 973 case VT_LDOUBLE: 864 #ifdef TCC_ARM_HARDFLOAT 865 if (!variadic) { 866 int hfa = 0; /* Homogeneous float aggregate */ 974 if (float_abi == ARM_HARD_FLOAT) { 975 int is_hfa = 0; /* Homogeneous float aggregate */ 867 976 868 977 if (is_float(vtop[-i].type.t) 869 || (hfa = is_float_hgen_aggr(&vtop[-i].type))) { 870 int end_reg; 871 872 assigned_vfpreg = assign_fpreg(&avregs, align, size); 873 end_reg = assigned_vfpreg + (size - 1) / 4; 874 if (assigned_vfpreg >= 0) { 875 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2; 876 if (hfa) { 877 /* before_stack can only have been set because all core registers 878 are assigned, so no need to care about before_vfpreg_hfa if 879 before_stack is set */ 880 if (before_stack) { 881 vrote(&vtop[-i], &vtop[-i] - before_stack); 882 before_stack++; 883 } else if (!before_vfpreg_hfa) 884 before_vfpreg_hfa = &vtop[-i-1]; 885 for (j = assigned_vfpreg; j <= end_reg; j++) 886 vfp_todo|=(1<<j); 887 } 978 || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { 979 int end_vfpreg; 980 981 start_vfpreg = assign_vfpreg(&avregs, align, size); 982 end_vfpreg = start_vfpreg + ((size - 1) >> 2); 983 if (start_vfpreg >= 0) { 984 pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]}; 985 if (is_hfa) 986 add_param_plan(plan, pplan, VFP_STRUCT_CLASS); 987 else 988 add_param_plan(plan, pplan, VFP_CLASS); 888 989 continue; 889 } else { 890 if (!hfa) 891 vfp_argno++; 892 /* No need to update before_stack as no more hfa can be allocated in 893 VFP regs */ 894 if (!before_vfpreg_hfa) 895 before_vfpreg_hfa = &vtop[-i-1]; 990 } else 896 991 break; 897 }898 992 } 899 993 } 900 #endif 901 ncrn = (ncrn + (align-1)/4) & -(align/4); 902 size = (size + 3) & -4; 903 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) { 904 /* Either there is HFA in VFP registers, or there is arguments on stack, 905 it cannot be both. Hence either before_stack already points after 906 the slot where the vtop[-i] SValue is moved, or before_stack will not 907 be used */ 908 if (before_vfpreg_hfa) { 909 vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa); 910 before_vfpreg_hfa++; 911 } 994 ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1); 995 if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { 996 /* The parameter is allocated both in core register and on stack. As 997 * such, it can be of either class: it would either be the last of 998 * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ 912 999 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) 913 todo|=(1<<j); 914 ncrn+=size/4; 915 if (ncrn > 4) { 916 args_size = (ncrn - 4) * 4; 917 if (!before_stack) 918 before_stack = &vtop[-i-1]; 919 } 920 } 921 else { 1000 *todo|=(1<<j); 1001 pplan = (struct param_plan) {ncrn, j, &vtop[-i]}; 1002 add_param_plan(plan, pplan, CORE_STRUCT_CLASS); 1003 ncrn += size/4; 1004 if (ncrn > 4) 1005 nsaa = (ncrn - 4) * 4; 1006 } else { 922 1007 ncrn = 4; 923 /* No need to set before_vfpreg_hfa if not set since there will no924 longer be any structure assigned to core registers */925 if (!before_stack)926 before_stack = &vtop[-i-1];927 1008 break; 928 1009 } 929 1010 continue; 930 1011 default: 931 #ifdef TCC_ARM_EABI932 if (!i) {933 break;934 }935 #endif936 1012 if (ncrn < 4) { 937 1013 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; … … 939 1015 if (is_long) { 940 1016 ncrn = (ncrn + 1) & -2; 941 if (ncrn == 4) { 942 argno++; 1017 if (ncrn == 4) 943 1018 break; 1019 } 1020 pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]}; 1021 ncrn++; 1022 if (is_long) 1023 pplan.end = ncrn++; 1024 add_param_plan(plan, pplan, CORE_CLASS); 1025 continue; 1026 } 1027 } 1028 nsaa = (nsaa + (align - 1)) & ~(align - 1); 1029 pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]}; 1030 add_param_plan(plan, pplan, STACK_CLASS); 1031 nsaa += size; /* size already rounded up before */ 1032 } 1033 return nsaa; 1034 } 1035 1036 #undef add_param_plan 1037 1038 /* Copy parameters to their final destination (core reg, VFP reg or stack) for 1039 function call. 1040 1041 nb_args: number of parameters the function take 1042 plan: the overall assignment plan for parameters 1043 todo: a bitmap indicating what core reg will hold a parameter 1044 1045 Returns the number of SValue added by this function on the value stack */ 1046 static int copy_params(int nb_args, struct plan *plan, int todo) 1047 { 1048 int size, align, r, i, nb_extra_sval = 0; 1049 struct param_plan *pplan; 1050 int pass = 0; 1051 1052 /* Several constraints require parameters to be copied in a specific order: 1053 - structures are copied to the stack before being loaded in a reg; 1054 - floats loaded to an odd numbered VFP reg are first copied to the 1055 preceding even numbered VFP reg and then moved to the next VFP reg. 1056 1057 It is thus important that: 1058 - structures assigned to core regs must be copied after parameters 1059 assigned to the stack but before structures assigned to VFP regs because 1060 a structure can lie partly in core registers and partly on the stack; 1061 - parameters assigned to the stack and all structures be copied before 1062 parameters assigned to a core reg since copying a parameter to the stack 1063 require using a core reg; 1064 - parameters assigned to VFP regs be copied before structures assigned to 1065 VFP regs as the copy might use an even numbered VFP reg that already 1066 holds part of a structure. */ 1067 again: 1068 for(i = 0; i < NB_CLASSES; i++) { 1069 for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { 1070 1071 if (pass 1072 && (i != CORE_CLASS || pplan->sval->r < VT_CONST)) 1073 continue; 1074 1075 vpushv(pplan->sval); 1076 pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ 1077 switch(i) { 1078 case STACK_CLASS: 1079 case CORE_STRUCT_CLASS: 1080 case VFP_STRUCT_CLASS: 1081 if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { 1082 int padding = 0; 1083 size = type_size(&pplan->sval->type, &align); 1084 /* align to stack align size */ 1085 size = (size + 3) & ~3; 1086 if (i == STACK_CLASS && pplan->prev) 1087 padding = pplan->start - pplan->prev->end; 1088 size += padding; /* Add padding if any */ 1089 /* allocate the necessary size on stack */ 1090 gadd_sp(-size); 1091 /* generate structure store */ 1092 r = get_reg(RC_INT); 1093 o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */ 1094 vset(&vtop->type, r | VT_LVAL, 0); 1095 vswap(); 1096 vstore(); /* memcpy to current sp + potential padding */ 1097 1098 /* Homogeneous float aggregate are loaded to VFP registers 1099 immediately since there is no way of loading data in multiple 1100 non consecutive VFP registers as what is done for other 1101 structures (see the use of todo). */ 1102 if (i == VFP_STRUCT_CLASS) { 1103 int first = pplan->start, nb = pplan->end - first + 1; 1104 /* vpop.32 {pplan->start, ..., pplan->end} */ 1105 o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); 1106 /* No need to write the register used to a SValue since VFP regs 1107 cannot be used for gcall_or_jmp */ 1108 } 1109 } else { 1110 if (is_float(pplan->sval->type.t)) { 1111 #ifdef TCC_ARM_VFP 1112 r = vfpr(gv(RC_FLOAT)) << 12; 1113 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) 1114 size = 4; 1115 else { 1116 size = 8; 1117 r |= 0x101; /* vpush.32 -> vpush.64 */ 1118 } 1119 o(0xED2D0A01 + r); /* vpush */ 1120 #else 1121 r = fpr(gv(RC_FLOAT)) << 12; 1122 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) 1123 size = 4; 1124 else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) 1125 size = 8; 1126 else 1127 size = LDOUBLE_SIZE; 1128 1129 if (size == 12) 1130 r |= 0x400000; 1131 else if(size == 8) 1132 r|=0x8000; 1133 1134 o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ 1135 #endif 1136 } else { 1137 /* simple type (currently always same size) */ 1138 /* XXX: implicit cast ? */ 1139 size=4; 1140 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { 1141 lexpand_nr(); 1142 size = 8; 1143 r = gv(RC_INT); 1144 o(0xE52D0004|(intr(r)<<12)); /* push r */ 1145 vtop--; 1146 } 1147 r = gv(RC_INT); 1148 o(0xE52D0004|(intr(r)<<12)); /* push r */ 1149 } 1150 if (i == STACK_CLASS && pplan->prev) 1151 gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */ 944 1152 } 1153 break; 1154 1155 case VFP_CLASS: 1156 gv(regmask(TREG_F0 + (pplan->start >> 1))); 1157 if (pplan->start & 1) { /* Must be in upper part of double register */ 1158 o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ 1159 vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ 1160 } 1161 break; 1162 1163 case CORE_CLASS: 1164 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { 1165 lexpand_nr(); 1166 gv(regmask(pplan->end)); 1167 pplan->sval->r2 = vtop->r; 1168 vtop--; 1169 } 1170 gv(regmask(pplan->start)); 1171 /* Mark register as used so that gcall_or_jmp use another one 1172 (regs >=4 are free as never used to pass parameters) */ 1173 pplan->sval->r = vtop->r; 1174 break; 1175 } 1176 vtop--; 1177 } 1178 } 1179 1180 /* second pass to restore registers that were saved on stack by accident. 1181 Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */ 1182 if (++pass < 2) 1183 goto again; 1184 1185 /* Manually free remaining registers since next parameters are loaded 1186 * manually, without the help of gv(int). */ 1187 save_regs(nb_args); 1188 1189 if(todo) { 1190 o(0xE8BD0000|todo); /* pop {todo} */ 1191 for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { 1192 int r; 1193 pplan->sval->r = pplan->start; 1194 /* An SValue can only pin 2 registers at best (r and r2) but a structure 1195 can occupy more than 2 registers. Thus, we need to push on the value 1196 stack some fake parameter to have on SValue for each registers used 1197 by a structure (r2 is not used). */ 1198 for (r = pplan->start + 1; r <= pplan->end; r++) { 1199 if (todo & (1 << r)) { 1200 nb_extra_sval++; 1201 vpushi(0); 1202 vtop->r = r; 945 1203 } 946 plan[argno++][0]=ncrn++; 947 if (is_long) { 948 plan[argno-1][1]=ncrn++; 949 } 950 continue; 951 } 952 argno++; 953 } 1204 } 1205 } 1206 } 1207 return nb_extra_sval; 1208 } 1209 1210 /* Generate function call. The function address is pushed first, then 1211 all the parameters in call order. This functions pops all the 1212 parameters and the function address. */ 1213 void gfunc_call(int nb_args) 1214 { 1215 int r, args_size; 1216 int def_float_abi = float_abi; 1217 int todo; 1218 struct plan plan; 1219 954 1220 #ifdef TCC_ARM_EABI 955 if(args_size & (align-1)) { 956 vpushi(0); 957 vtop->type.t = VT_VOID; /* padding */ 958 vrott(i+2); 959 args_size += 4; 960 nb_args++; 961 argno++; 962 } 963 #endif 964 args_size += (size + 3) & -4; 965 } 1221 int variadic; 1222 1223 if (float_abi == ARM_HARD_FLOAT) { 1224 variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); 1225 if (variadic || floats_in_core_regs(&vtop[-nb_args])) 1226 float_abi = ARM_SOFTFP_FLOAT; 1227 } 1228 #endif 1229 /* cannot let cpu flags if other instruction are generated. Also avoid leaving 1230 VT_JMP anywhere except on the top of the stack because it would complicate 1231 the code generator. */ 1232 r = vtop->r & VT_VALMASK; 1233 if (r == VT_CMP || (r & ~1) == VT_JMP) 1234 gv(RC_INT); 1235 1236 args_size = assign_regs(nb_args, float_abi, &plan, &todo); 1237 966 1238 #ifdef TCC_ARM_EABI 967 vtop--, nb_args--; 968 #endif 969 args_size = keep = 0; 970 for(i = 0;i < nb_args; i++) { 971 vrotb(keep+1); 972 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { 973 size = type_size(&vtop->type, &align); 974 /* align to stack align size */ 975 size = (size + 3) & -4; 976 /* allocate the necessary size on stack */ 977 gadd_sp(-size); 978 /* generate structure store */ 979 r = get_reg(RC_INT); 980 o(0xE1A0000D|(intr(r)<<12)); 981 vset(&vtop->type, r | VT_LVAL, 0); 982 vswap(); 983 vstore(); 984 vtop--; 985 args_size += size; 986 } else if (is_float(vtop->type.t)) { 987 #ifdef TCC_ARM_HARDFLOAT 988 if (!variadic && --vfp_argno<16 && vfp_plan[vfp_argno]!=-1) { 989 plan2[keep++]=vfp_plan[vfp_argno]; 990 continue; 991 } 992 #endif 993 #ifdef TCC_ARM_VFP 994 r=vfpr(gv(RC_FLOAT))<<12; 995 size=4; 996 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) 997 { 998 size=8; 999 r|=0x101; /* fstms -> fstmd */ 1000 } 1001 o(0xED2D0A01+r); 1002 #else 1003 r=fpr(gv(RC_FLOAT))<<12; 1004 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) 1005 size = 4; 1006 else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) 1007 size = 8; 1008 else 1009 size = LDOUBLE_SIZE; 1010 1011 if (size == 12) 1012 r|=0x400000; 1013 else if(size == 8) 1014 r|=0x8000; 1015 1016 o(0xED2D0100|r|(size>>2)); 1017 #endif 1018 vtop--; 1019 args_size += size; 1020 } else { 1021 int s; 1022 /* simple type (currently always same size) */ 1023 /* XXX: implicit cast ? */ 1024 size=4; 1025 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { 1026 lexpand_nr(); 1027 s=-1; 1028 if(--argno<4 && plan[argno][1]!=-1) 1029 s=plan[argno][1]; 1030 argno++; 1031 size = 8; 1032 if(s==-1) { 1033 r = gv(RC_INT); 1034 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */ 1035 vtop--; 1036 } else { 1037 size=0; 1038 plan2[keep]=s; 1039 keep++; 1040 vswap(); 1041 } 1042 } 1043 s=-1; 1044 if(--argno<4 && plan[argno][0]!=-1) 1045 s=plan[argno][0]; 1046 #ifdef TCC_ARM_EABI 1047 if(vtop->type.t == VT_VOID) { 1048 if(s == -1) 1049 o(0xE24DD004); /* sub sp,sp,#4 */ 1050 vtop--; 1051 } else 1052 #endif 1053 if(s == -1) { 1054 r = gv(RC_INT); 1055 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */ 1056 vtop--; 1057 } else { 1058 size=0; 1059 plan2[keep]=s; 1060 keep++; 1061 } 1062 args_size += size; 1063 } 1064 } 1065 for(i = 0; i < keep; i++) { 1066 vrotb(keep); 1067 gv(regmask(plan2[i])); 1068 #ifdef TCC_ARM_HARDFLOAT 1069 /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */ 1070 if (i < keep - 1 && is_float(vtop->type.t) && (plan2[i] <= plan2[i + 1])) { 1071 o(0xEEF00A40|(vfpr(plan2[i])<<12)|vfpr(plan2[i])); 1072 } 1073 #endif 1074 } 1075 save_regs(keep); /* save used temporary registers */ 1076 keep++; 1077 if(ncrn) { 1078 int nb_regs=0; 1079 if (ncrn>4) 1080 ncrn=4; 1081 todo&=((1<<ncrn)-1); 1082 if(todo) { 1083 int i; 1084 o(0xE8BD0000|todo); 1085 for(i=0;i<4;i++) 1086 if(todo&(1<<i)) { 1087 vpushi(0); 1088 vtop->r=i; 1089 keep++; 1090 nb_regs++; 1091 } 1092 } 1093 args_size-=nb_regs*4; 1094 } 1095 if(vfp_todo) { 1096 int nb_fregs=0; 1097 1098 for(i=0;i<16;i++) 1099 if(vfp_todo&(1<<i)) { 1100 o(0xED9D0A00|(i&1)<<22|(i>>1)<<12|nb_fregs); 1101 vpushi(0); 1102 /* There might be 2 floats in a double VFP reg but that doesn't seem 1103 to matter */ 1104 if (!(i%2)) 1105 vtop->r=TREG_F0+i/2; 1106 keep++; 1107 nb_fregs++; 1108 } 1109 if (nb_fregs) { 1110 gadd_sp(nb_fregs*4); 1111 args_size-=nb_fregs*4; 1112 } 1113 } 1114 vrotb(keep); 1239 if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ 1240 args_size = (args_size + 7) & ~7; 1241 o(0xE24DD004); /* sub sp, sp, #4 */ 1242 } 1243 #endif 1244 1245 nb_args += copy_params(nb_args, &plan, todo); 1246 tcc_free(plan.pplans); 1247 1248 /* Move fct SValue on top as required by gcall_or_jmp */ 1249 vrotb(nb_args + 1); 1115 1250 gcall_or_jmp(0); 1116 1251 if (args_size) 1117 gadd_sp(args_size); 1118 #ifdef TCC_ARM_EABI 1119 if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT 1120 && type_size(&vtop->type.ref->type, &align) <= 4) 1121 { 1122 store(REG_IRET,vtop-keep); 1123 ++keep; 1124 } 1125 #ifdef TCC_ARM_VFP 1126 #ifdef TCC_ARM_HARDFLOAT 1127 else if(variadic && is_float(vtop->type.ref->type.t)) { 1128 #else 1129 else if(is_float(vtop->type.ref->type.t)) { 1130 #endif 1252 gadd_sp(args_size); /* pop all parameters passed on the stack */ 1253 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) 1254 if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { 1131 1255 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { 1132 o(0xEE000A10); /* fmsr s0,r0 */1256 o(0xEE000A10); /*vmov s0, r0 */ 1133 1257 } else { 1134 o(0xEE000B10); /* fmdlr d0,r0 */1135 o(0xEE201B10); /* fmdhr d0,r1 */1136 } 1137 } 1138 #endif 1139 #endif 1140 vtop-=keep;1141 leaffunc = 0;1258 o(0xEE000B10); /* vmov.32 d0[0], r0 */ 1259 o(0xEE201B10); /* vmov.32 d0[1], r1 */ 1260 } 1261 } 1262 #endif 1263 vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ 1264 leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ 1265 float_abi = def_float_abi; 1142 1266 } 1143 1267 … … 1146 1270 { 1147 1271 Sym *sym,*sym2; 1148 int n,nf,size,align, variadic, struct_ret = 0; 1149 #ifdef TCC_ARM_HARDFLOAT 1272 int n, nf, size, align, rs, struct_ret = 0; 1273 int addr, pn, sn; /* pn=core, sn=stack */ 1274 CType ret_type; 1275 1276 #ifdef TCC_ARM_EABI 1150 1277 struct avail_regs avregs = AVAIL_REGS_INITIALIZER; 1151 1278 #endif … … 1153 1280 sym = func_type->ref; 1154 1281 func_vt = sym->type; 1282 func_var = (func_type->ref->f.func_type == FUNC_ELLIPSIS); 1155 1283 1156 1284 n = nf = 0; 1157 variadic = (func_type->ref->c == FUNC_ELLIPSIS); 1158 if((func_vt.t & VT_BTYPE) == VT_STRUCT 1159 && type_size(&func_vt,&align) > 4) 1285 if ((func_vt.t & VT_BTYPE) == VT_STRUCT && 1286 !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs)) 1160 1287 { 1161 1288 n++; … … 1163 1290 func_vc = 12; /* Offset from fp of the place to store the result */ 1164 1291 } 1165 for(sym2 =sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) {1292 for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { 1166 1293 size = type_size(&sym2->type, &align); 1167 #ifdef TCC_ARM_HARDFLOAT 1168 if (!variadic && (is_float(sym2->type.t) 1169 || is_float_hgen_aggr(&sym2->type))) { 1170 int tmpnf = assign_fpreg(&avregs, align, size) + 1; 1294 #ifdef TCC_ARM_EABI 1295 if (float_abi == ARM_HARD_FLOAT && !func_var && 1296 (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { 1297 int tmpnf = assign_vfpreg(&avregs, align, size); 1298 tmpnf += (size + 3) / 4; 1171 1299 nf = (tmpnf > nf) ? tmpnf : nf; 1172 1300 } else … … 1176 1304 } 1177 1305 o(0xE1A0C00D); /* mov ip,sp */ 1178 if (variadic)1306 if (func_var) 1179 1307 n=4; 1180 if (n) {1308 if (n) { 1181 1309 if(n>4) 1182 1310 n=4; … … 1195 1323 o(0xE1A0B00D); /* mov fp, sp */ 1196 1324 func_sub_sp_offset = ind; 1197 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog ue*/1198 { 1199 int addr, pn = struct_ret, sn = 0; /* pn=core, sn=stack */ 1200 1201 #ifdef TCC_ARM_HARDFLOAT 1325 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ 1326 1327 #ifdef TCC_ARM_EABI 1328 if (float_abi == ARM_HARD_FLOAT) { 1329 func_vc += nf * 4; 1202 1330 avregs = AVAIL_REGS_INITIALIZER; 1203 #endif 1204 while ((sym = sym->next)) { 1205 CType *type; 1206 type = &sym->type; 1207 size = type_size(type, &align); 1208 size = (size + 3) >> 2; 1209 align = (align + 3) & ~3; 1210 #ifdef TCC_ARM_HARDFLOAT 1211 if (!variadic && (is_float(sym->type.t) 1212 || is_float_hgen_aggr(&sym->type))) { 1213 int fpn = assign_fpreg(&avregs, align, size << 2); 1214 if (fpn >= 0) { 1215 addr = fpn * 4; 1216 } else 1217 goto from_stack; 1218 } else 1219 #endif 1220 if (pn < 4) { 1331 } 1332 #endif 1333 pn = struct_ret, sn = 0; 1334 while ((sym = sym->next)) { 1335 CType *type; 1336 type = &sym->type; 1337 size = type_size(type, &align); 1338 size = (size + 3) >> 2; 1339 align = (align + 3) & ~3; 1340 #ifdef TCC_ARM_EABI 1341 if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) 1342 || is_hgen_float_aggr(&sym->type))) { 1343 int fpn = assign_vfpreg(&avregs, align, size << 2); 1344 if (fpn >= 0) 1345 addr = fpn * 4; 1346 else 1347 goto from_stack; 1348 } else 1349 #endif 1350 if (pn < 4) { 1221 1351 #ifdef TCC_ARM_EABI 1222 1352 pn = (pn + (align-1)/4) & -(align/4); 1223 1353 #endif 1224 1225 1226 1227 1228 1229 #ifdef TCC_ARM_ HARDFLOAT1354 addr = (nf + pn) * 4; 1355 pn += size; 1356 if (!sn && pn > 4) 1357 sn = (pn - 4); 1358 } else { 1359 #ifdef TCC_ARM_EABI 1230 1360 from_stack: 1231 #endif1232 #ifdef TCC_ARM_EABI1233 1361 sn = (sn + (align-1)/4) & -(align/4); 1234 1362 #endif 1235 1236 1237 1238 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr+12);1239 }1363 addr = (n + nf + sn) * 4; 1364 sn += size; 1365 } 1366 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), 1367 addr + 12); 1240 1368 } 1241 1369 last_itod_magic=0; … … 1249 1377 uint32_t x; 1250 1378 int diff; 1251 #ifdef TCC_ARM_EABI 1252 /* Useless but harmless copy of the float result into main register(s) in case1253 of variadic function in the hardfloat variant */ 1254 if (is_float(func_vt.t)) {1379 /* Copy float return value to core register if base standard is used and 1380 float computation is made with VFP */ 1381 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) 1382 if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { 1255 1383 if((func_vt.t & VT_BTYPE) == VT_FLOAT) 1256 1384 o(0xEE100A10); /* fmrs r0, s0 */ … … 1287 1415 { 1288 1416 int r; 1417 if (nocode_wanted) 1418 return t; 1289 1419 r=ind; 1290 1420 o(0xE0000000|encbranch(r,t,1)); … … 1303 1433 int v, r; 1304 1434 uint32_t op; 1435 1305 1436 v = vtop->r & VT_VALMASK; 1306 1437 r=ind; 1307 if (v == VT_CMP) { 1438 1439 if (nocode_wanted) { 1440 ; 1441 } else if (v == VT_CMP) { 1308 1442 op=mapcc(inv?negcc(vtop->c.i):vtop->c.i); 1309 1443 op|=encbranch(r,t,1); … … 1332 1466 gsym(vtop->c.i); 1333 1467 } 1334 } else {1335 if (is_float(vtop->type.t)) {1336 r=gv(RC_FLOAT);1337 #ifdef TCC_ARM_VFP1338 o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */1339 o(0xEEF1FA10); /* fmstat */1340 #else1341 o(0xEE90F118|(fpr(r)<<16));1342 #endif1343 vtop->r = VT_CMP;1344 vtop->c.i = TOK_NE;1345 return gtst(inv, t);1346 } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1347 /* constant jmp optimization */1348 if ((vtop->c.i != 0) != inv)1349 t = gjmp(t);1350 } else {1351 v = gv(RC_INT);1352 o(0xE3300000|(intr(v)<<16));1353 vtop->r = VT_CMP;1354 vtop->c.i = TOK_NE;1355 return gtst(inv, t);1356 }1357 1468 } 1358 1469 vtop--; … … 1543 1654 1544 1655 /* generate a floating point operation 'v = t1 op t2' instruction. The 1545 * two operands are guarante d to have the same floating point type */1656 * two operands are guaranteed to have the same floating point type */ 1546 1657 void gen_opf(int op) 1547 1658 { … … 1612 1723 case TOK_UGT: op=TOK_GT; break; 1613 1724 } 1614 1725 1615 1726 vtop->r = VT_CMP; 1616 1727 vtop->c.i = op; … … 1673 1784 1674 1785 /* generate a floating point operation 'v = t1 op t2' instruction. The 1675 two operands are guarante d to have the same floating point type */1786 two operands are guaranteed to have the same floating point type */ 1676 1787 void gen_opf(int op) 1677 1788 { … … 1763 1874 vswap(); 1764 1875 r2=fpr(gv(RC_FLOAT)); 1765 } 1876 } 1766 1877 break; 1767 1878 default: … … 1775 1886 case TOK_ULE: 1776 1887 case TOK_UGT: 1777 tcc_error("unsigned comparis ion on floats?");1888 tcc_error("unsigned comparison on floats?"); 1778 1889 break; 1779 1890 case TOK_LT: … … 2000 2111 } 2001 2112 2113 /* Save the stack pointer onto the stack and return the location of its address */ 2114 ST_FUNC void gen_vla_sp_save(int addr) { 2115 SValue v; 2116 v.type.t = VT_PTR; 2117 v.r = VT_LOCAL | VT_LVAL; 2118 v.c.i = addr; 2119 store(TREG_SP, &v); 2120 } 2121 2122 /* Restore the SP from a location on the stack */ 2123 ST_FUNC void gen_vla_sp_restore(int addr) { 2124 SValue v; 2125 v.type.t = VT_PTR; 2126 v.r = VT_LOCAL | VT_LVAL; 2127 v.c.i = addr; 2128 load(TREG_SP, &v); 2129 } 2130 2131 /* Subtract from the stack pointer, and push the resulting value onto the stack */ 2132 ST_FUNC void gen_vla_alloc(CType *type, int align) { 2133 int r = intr(gv(RC_INT)); 2134 o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */ 2135 #ifdef TCC_ARM_EABI 2136 if (align < 8) 2137 align = 8; 2138 #else 2139 if (align < 4) 2140 align = 4; 2141 #endif 2142 if (align & (align - 1)) 2143 tcc_error("alignment is not a power of 2: %i", align); 2144 o(stuff_const(0xE3C0D000|(r<<16), align - 1)); /* bic sp, r, #align-1 */ 2145 vpop(); 2146 } 2147 2002 2148 /* end of ARM code generator */ 2003 2149 /*************************************************************/
Note:
See TracChangeset
for help on using the changeset viewer.