History

Add support for arm hardfloat calling convention

See Procedure Call Standard for the ARM Architecture (AAPCS) for more details.

Thomas Preud'homme committed 14 years ago

Commit 7f6095b1 parent bfb00495 files · +330 −76Browse files

Unified · Split

5 files
  1. Changelog +1 −0
  2. Makefile +2 −0
  3. arm-gen.c +310 −70
  4. tcc.h +3 −0
  5. tccgen.c +14 −6
Changelog+1−0
@@ -14,6 +14,7 @@ not released: · 13 unmodified lines
14- Support indirect functions as externals (Thomas Preud'homme)14- Support indirect functions as externals (Thomas Preud'homme)
15- Add support for C99 variable length arrays (Thomas Preud'homme & Joe Soroka)15- Add support for C99 variable length arrays (Thomas Preud'homme & Joe Soroka)
16- Improve support of ARM (Daniel Gl�ckner)16- Improve support of ARM (Daniel Gl�ckner)
17- Support ARM hardfloat calling convention (Thomas Preud'homme)
17 18
18version 0.9.25:19version 0.9.25:
19 20
Makefile+2−0
@@ -54,6 +54,8 @@ NATIVE_DEFINES+=-DWITHOUT_LIBTCC · 53 unmodified lines
54NATIVE_DEFINES+=$(if $(wildcard /lib/ld-linux.so.3),-DTCC_ARM_EABI)54NATIVE_DEFINES+=$(if $(wildcard /lib/ld-linux.so.3),-DTCC_ARM_EABI)
55NATIVE_DEFINES+=$(if $(wildcard /lib/arm-linux-gnueabi),-DCONFIG_MULTIARCHDIR=\"arm-linux-gnueabi\")55NATIVE_DEFINES+=$(if $(wildcard /lib/arm-linux-gnueabi),-DCONFIG_MULTIARCHDIR=\"arm-linux-gnueabi\")
56NATIVE_DEFINES+=$(if $(shell grep -l "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo),-DTCC_ARM_VFP)56NATIVE_DEFINES+=$(if $(shell grep -l "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo),-DTCC_ARM_VFP)
57# To use ARM hardfloat calling convension
58#NATIVE_DEFINES+=-DTCC_ARM_HARDFLOAT
57endif59endif
58 60
59ifdef CONFIG_WIN3261ifdef CONFIG_WIN32
arm-gen.c+310−70
@@ -737,16 +737,85 @@ static void gcall_or_jmp(int is_jmp) · 736 unmodified lines
737 }737 }
738}738}
739 739
740#ifdef TCC_ARM_HARDFLOAT
741static int is_float_hgen_aggr(CType *type)
742{
743 if ((type->t & VT_BTYPE) == VT_STRUCT) {
744 struct Sym *ref;
745 int btype, nb_fields = 0;
746
747 ref = type->ref;
748 btype = ref->type.t & VT_BTYPE;
749 if (btype == VT_FLOAT || btype == VT_DOUBLE) {
750 for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
751 return !ref && nb_fields <= 4;
752 }
753 }
754 return 0;
755}
756
757struct avail_regs {
758 /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */
759 signed char avail[3];
760 int first_hole;
761 int last_hole;
762 int first_free_reg;
763};
764
765#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
766
767/* Assign a register for a CPRC param with correct size and alignment
768 * size and align are in bytes, as returned by type_size */
769int assign_fpreg(struct avail_regs *avregs, int align, int size)
770{
771 int first_reg = 0;
772
773 if (avregs->first_free_reg == -1)
774 return -1;
775 if (align >> 3) { // alignment needed (base type: double)
776 first_reg = avregs->first_free_reg;
777 if (first_reg & 1)
778 avregs->avail[avregs->last_hole++] = first_reg++;
779 } else {
780 if (size == 4 && avregs->first_hole != avregs->last_hole)
781 return avregs->avail[avregs->first_hole++];
782 else
783 first_reg = avregs->first_free_reg;
784 }
785 if (first_reg + size / 4 <= 16) {
786 avregs->first_free_reg = first_reg + size / 4;
787 return first_reg;
788 }
789 avregs->first_free_reg = -1;
790 return -1;
791}
792#endif
793
740/* Generate function call. The function address is pushed first, then794/* Generate function call. The function address is pushed first, then
741 all the parameters in call order. This functions pops all the795 all the parameters in call order. This functions pops all the
742 parameters and the function address. */796 parameters and the function address. */
743void gfunc_call(int nb_args)797void gfunc_call(int nb_args)
744{798{
745 int size, align, r, args_size, i;799 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno;
746 Sym *func_sym;
747 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};800 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
748 int todo=0xf, keep, plan2[4]={0,0,0,0};801 SValue *before_stack = NULL; /* SValue before first on stack argument */
802 SValue *before_vfpreg_hfa = NULL; /* SValue before first in VFP reg hfa argument */
803#ifdef TCC_ARM_HARDFLOAT
804 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
805 signed char vfp_plan[16];
806 int plan2[4+16];
807 int variadic;
808#else
809 int plan2[4]={0,0,0,0};
810#endif
811 int vfp_todo=0;
812 int todo=0, keep;
749 813
814#ifdef TCC_ARM_HARDFLOAT
815 memset(vfp_plan, -1, sizeof(vfp_plan));
816 memset(plan2, 0, sizeof(plan2));
817 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
818#endif
750 r = vtop->r & VT_VALMASK;819 r = vtop->r & VT_VALMASK;
751 if (r == VT_CMP || (r & ~1) == VT_JMP)820 if (r == VT_CMP || (r & ~1) == VT_JMP)
752 gv(RC_INT);821 gv(RC_INT);
@@ -763,39 +832,128 @@ void gfunc_call(int nb_args) · 10 unmodified lines
763 vpushi(0);832 vpushi(0);
764 vtop->type.t = VT_LLONG;833 vtop->type.t = VT_LLONG;
765 args_size = 0;834 args_size = 0;
835#endif
836 ncrn = ncprn = argno = vfp_argno = 0;
837 /* Assign argument to registers and stack with alignment.
838 If, considering alignment constraints, enough registers of the correct type
839 (core or VFP) are free for the current argument, assign them to it, else
840 allocate on stack with correct alignment. Whenever a structure is allocated
841 in registers or on stack, it is always put on the stack at this stage. The
842 stack is divided in 3 zones. The zone are, from low addresses to high
843 addresses: structures to be loaded in core registers, structures to be
844 loaded in VFP registers, argument allocated to stack. SValue's representing
845 structures in the first zone are moved just after the SValue pointed by
846 before_vfpreg_hfa. SValue's representing structures in the second zone are
847 moved just after the SValue pointer by before_stack. */
766 for(i = nb_args + 1 ; i-- ;) {848 for(i = nb_args + 1 ; i-- ;) {
849 int j, assigned_vfpreg = 0;
767 size = type_size(&vtop[-i].type, &align);850 size = type_size(&vtop[-i].type, &align);
768 if(args_size & (align-1)) {
769 vpushi(0);
770 vtop->type.t = VT_VOID; /* padding */
771 vrott(i+2);
772 args_size += 4;
773 ++nb_args;
774 }
775 args_size += (size + 3) & -4;
776 }
777 vtop--;
778#endif
779 args_size = 0;
780 for(i = nb_args ; i-- && args_size < 16 ;) {
781 switch(vtop[-i].type.t & VT_BTYPE) {851 switch(vtop[-i].type.t & VT_BTYPE) {
782 case VT_STRUCT:852 case VT_STRUCT:
783 case VT_FLOAT:853 case VT_FLOAT:
784 case VT_DOUBLE:854 case VT_DOUBLE:
785 case VT_LDOUBLE:855 case VT_LDOUBLE:
786 size = type_size(&vtop[-i].type, &align);856#ifdef TCC_ARM_HARDFLOAT
787 size = (size + 3) & -4;857 if (!variadic) {
788 args_size += size;858 int hfa = 0; /* Homogeneous float aggregate */
859
860 if (is_float(vtop[-i].type.t)
861 || (hfa = is_float_hgen_aggr(&vtop[-i].type))) {
862 int end_reg;
863
864 assigned_vfpreg = assign_fpreg(&avregs, align, size);
865 end_reg = assigned_vfpreg + (size - 1) / 4;
866 if (assigned_vfpreg >= 0) {
867 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2;
868 if (hfa) {
869 /* before_stack can only have been set because all core registers
870 are assigned, so no need to care about before_vfpreg_hfa if
871 before_stack is set */
872 if (before_stack) {
873 vrote(&vtop[-i], &vtop[-i] - before_stack);
874 before_stack++;
875 } else if (!before_vfpreg_hfa)
876 before_vfpreg_hfa = &vtop[-i-1];
877 for (j = assigned_vfpreg; j <= end_reg; j++)
878 vfp_todo|=(1<<j);
879 }
880 continue;
881 } else {
882 if (!hfa)
883 vfp_argno++;
884 /* No need to update before_stack as no more hfa can be allocated in
885 VFP regs */
886 if (!before_vfpreg_hfa)
887 before_vfpreg_hfa = &vtop[-i-1];
888 break;
889 }
890 }
891 }
892#endif
893 ncrn = (ncrn + (align-1)/4) & -(align/4);
894 size = (size + 3) & -4;
895 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) {
896 /* Either there is HFA in VFP registers, or there is arguments on stack,
897 it cannot be both. Hence either before_stack already points after
898 the slot where the vtop[-i] SValue is moved, or before_stack will not
899 be used */
900 if (before_vfpreg_hfa) {
901 vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa);
902 before_vfpreg_hfa++;
903 }
904 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
905 todo|=(1<<j);
906 ncrn+=size/4;
907 if (ncrn > 4) {
908 args_size = (ncrn - 4) * 4;
909 if (!before_stack)
910 before_stack = &vtop[-i-1];
911 }
912 }
913 else {
914 ncrn = 4;
915 /* No need to set before_vfpreg_hfa if not set since there will no
916 longer be any structure assigned to core registers */
917 if (!before_stack)
918 before_stack = &vtop[-i-1];
789 break;919 break;
920 }
921 continue;
790 default:922 default:
791 plan[nb_args-1-i][0]=args_size/4;923 if (!i) {
792 args_size += 4;924 break;
793 if ((vtop[-i].type.t & VT_BTYPE) == VT_LLONG && args_size < 16) {
794 plan[nb_args-1-i][1]=args_size/4;
795 args_size += 4;
796 }925 }
926 if (ncrn < 4) {
927 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
928
929 if (is_long) {
930 ncrn = (ncrn + 1) & -2;
931 if (ncrn == 4) {
932 argno++;
933 break;
934 }
935 }
936 plan[argno++][0]=ncrn++;
937 if (is_long) {
938 plan[argno-1][1]=ncrn++;
939 }
940 continue;
941 }
942 argno++;
797 }943 }
944#ifdef TCC_ARM_EABI
945 if(args_size & (align-1)) {
946 vpushi(0);
947 vtop->type.t = VT_VOID; /* padding */
948 vrott(i+2);
949 args_size += 4;
950 nb_args++;
951 argno++;
952 }
953#endif
954 args_size += (size + 3) & -4;
798 }955 }
956 vtop--;
799 args_size = keep = 0;957 args_size = keep = 0;
800 for(i = 0;i < nb_args; i++) {958 for(i = 0;i < nb_args; i++) {
801 vrotb(keep+1);959 vrotb(keep+1);
@@ -814,6 +972,12 @@ void gfunc_call(int nb_args) · 12 unmodified lines
814 vtop--;972 vtop--;
815 args_size += size;973 args_size += size;
816 } else if (is_float(vtop->type.t)) {974 } else if (is_float(vtop->type.t)) {
975#ifdef TCC_ARM_HARDFLOAT
976 if (!variadic && --vfp_argno<16 && vfp_plan[vfp_argno]!=-1) {
977 plan2[keep++]=vfp_plan[vfp_argno];
978 continue;
979 }
980#endif
817#ifdef TCC_ARM_VFP981#ifdef TCC_ARM_VFP
818 r=vfpr(gv(RC_FLOAT))<<12;982 r=vfpr(gv(RC_FLOAT))<<12;
819 size=4;983 size=4;
@@ -848,57 +1012,59 @@ void gfunc_call(int nb_args) · 28 unmodified lines
848 size=4;1012 size=4;
849 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {1013 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
850 lexpand_nr();1014 lexpand_nr();
851 s=RC_INT;1015 s=-1;
852 if(nb_args-i<5 && plan[nb_args-i-1][1]!=-1) {1016 if(--argno<4 && plan[argno][1]!=-1)
853 s=regmask(plan[nb_args-i-1][1]);1017 s=plan[argno][1];
854 todo&=~(1<<plan[nb_args-i-1][1]);1018 argno++;
855 }1019 size = 8;
856 if(s==RC_INT) {1020 if(s==-1) {
857 r = gv(s);1021 r = gv(RC_INT);
858 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */1022 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
859 vtop--;1023 vtop--;
860 } else {1024 } else {
1025 size=0;
861 plan2[keep]=s;1026 plan2[keep]=s;
862 keep++;1027 keep++;
863 vswap();1028 vswap();
864 }1029 }
865 size = 8;
866 }
867 s=RC_INT;
868 if(nb_args-i<5 && plan[nb_args-i-1][0]!=-1) {
869 s=regmask(plan[nb_args-i-1][0]);
870 todo&=~(1<<plan[nb_args-i-1][0]);
871 }1030 }
1031 s=-1;
1032 if(--argno<4 && plan[argno][0]!=-1)
1033 s=plan[argno][0];
872#ifdef TCC_ARM_EABI1034#ifdef TCC_ARM_EABI
873 if(vtop->type.t == VT_VOID) {1035 if(vtop->type.t == VT_VOID) {
874 if(s == RC_INT)1036 if(s == -1)
875 o(0xE24DD004); /* sub sp,sp,#4 */1037 o(0xE24DD004); /* sub sp,sp,#4 */
876 vtop--;1038 vtop--;
877 } else1039 } else
878#endif 1040#endif
879 if(s == RC_INT) {1041 if(s == -1) {
880 r = gv(s);1042 r = gv(RC_INT);
881 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */1043 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
882 vtop--;1044 vtop--;
883 } else {1045 } else {
1046 size=0;
884 plan2[keep]=s;1047 plan2[keep]=s;
885 keep++;1048 keep++;
886 }1049 }
887 args_size += size;1050 args_size += size;
888 }1051 }
889 }1052 }
890 for(i=keep;i--;) {1053 for(i = 0; i < keep; i++) {
891 gv(plan2[i]);1054 vrotb(keep);
892 vrott(keep);1055 gv(regmask(plan2[i]));
1056 /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */
1057 if (i < keep - 1 && is_float(vtop->type.t) && (plan2[i] <= plan2[i + 1])) {
1058 o(0xEEF00A40|(vfpr(plan2[i])<<12)|vfpr(plan2[i]));
1059 }
893 }1060 }
894save_regs(keep); /* save used temporary registers */1061save_regs(keep); /* save used temporary registers */
895 keep++;1062 keep++;
896 if(args_size) {1063 if(ncrn) {
897 int n;1064 int nb_regs=0;
898 n=args_size/4;1065 if (ncrn>4)
899 if(n>4)1066 ncrn=4;
900 n=4;1067 todo&=((1<<ncrn)-1);
901 todo&=((1<<n)-1);
902 if(todo) {1068 if(todo) {
903 int i;1069 int i;
904 o(0xE8BD0000|todo);1070 o(0xE8BD0000|todo);
@@ -907,12 +1073,31 @@ save_regs(keep); /* save used temporary registers */ · 2 unmodified lines
907 vpushi(0);1073 vpushi(0);
908 vtop->r=i;1074 vtop->r=i;
909 keep++;1075 keep++;
1076 nb_regs++;
910 }1077 }
911 }1078 }
912 args_size-=n*4;1079 args_size-=nb_regs*4;
1080 }
1081 if(vfp_todo) {
1082 int nb_fregs=0;
1083
1084 for(i=0;i<16;i++)
1085 if(vfp_todo&(1<<i)) {
1086 o(0xED9D0A00|(i&1)<<22|(i>>1)<<12|nb_fregs);
1087 vpushi(0);
1088 /* There might be 2 floats in a double VFP reg but that doesn't seem
1089 to matter */
1090 if (!(i%2))
1091 vtop->r=TREG_F0+i/2;
1092 keep++;
1093 nb_fregs++;
1094 }
1095 if (nb_fregs) {
1096 gadd_sp(nb_fregs*4);
1097 args_size-=nb_fregs*4;
1098 }
913 }1099 }
914 vrotb(keep);1100 vrotb(keep);
915 func_sym = vtop->type.ref;
916 gcall_or_jmp(0);1101 gcall_or_jmp(0);
917 if (args_size)1102 if (args_size)
918 gadd_sp(args_size);1103 gadd_sp(args_size);
@@ -924,7 +1109,11 @@ save_regs(keep); /* save used temporary registers */ · 5 unmodified lines
924 ++keep;1109 ++keep;
925 }1110 }
926#ifdef TCC_ARM_VFP1111#ifdef TCC_ARM_VFP
1112#ifdef TCC_ARM_HARDFLOAT
1113 else if(variadic && is_float(vtop->type.ref->type.t)) {
1114#else
927 else if(is_float(vtop->type.ref->type.t)) {1115 else if(is_float(vtop->type.ref->type.t)) {
1116#endif
928 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {1117 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
929 o(0xEE000A10); /* fmsr s0,r0 */1118 o(0xEE000A10); /* fmsr s0,r0 */
930 } else {1119 } else {
@@ -942,26 +1131,38 @@ save_regs(keep); /* save used temporary registers */ · 11 unmodified lines
942void gfunc_prolog(CType *func_type)1131void gfunc_prolog(CType *func_type)
943{1132{
944 Sym *sym,*sym2;1133 Sym *sym,*sym2;
945 int n,addr,size,align;1134 int n,nf,size,align, variadic, struct_ret = 0;
1135#ifdef TCC_ARM_HARDFLOAT
1136 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
1137#endif
946 1138
947 sym = func_type->ref;1139 sym = func_type->ref;
948 func_vt = sym->type;1140 func_vt = sym->type;
949 1141
950 n = 0;1142 n = nf = 0;
951 addr = 0;1143 variadic = (func_type->ref->c == FUNC_ELLIPSIS);
952 if((func_vt.t & VT_BTYPE) == VT_STRUCT1144 if((func_vt.t & VT_BTYPE) == VT_STRUCT
953 && type_size(&func_vt,&align) > 4)1145 && type_size(&func_vt,&align) > 4)
954 {1146 {
955 func_vc = addr;
956 addr += 4;
957 n++;1147 n++;
1148 struct_ret = 1;
958 }1149 }
959 for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) {1150 for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) {
960 size = type_size(&sym2->type, &align);1151 size = type_size(&sym2->type, &align);
961 n += (size + 3) / 4;1152#ifdef TCC_ARM_HARDFLOAT
1153 if (!variadic && (is_float(sym2->type.t)
1154 || is_float_hgen_aggr(&sym2->type))) {
1155 int tmpnf = assign_fpreg(&avregs, align, size) + 1;
1156 nf = (tmpnf > nf) ? tmpnf : nf;
1157 } else
1158#endif
1159 if (n < 4)
1160 n += (size + 3) / 4;
962 }1161 }
1162 if (struct_ret)
1163 func_vc = nf * 4;
963 o(0xE1A0C00D); /* mov ip,sp */1164 o(0xE1A0C00D); /* mov ip,sp */
964 if(func_type->ref->c == FUNC_ELLIPSIS)1165 if(variadic)
965 n=4;1166 n=4;
966 if(n) {1167 if(n) {
967 if(n>4)1168 if(n>4)
@@ -971,20 +1172,57 @@ void gfunc_prolog(CType *func_type) · 3 unmodified lines
971#endif1172#endif
972 o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */1173 o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */
973 }1174 }
1175 if (nf) {
1176 if (nf>16)
1177 nf=16;
1178 nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */
1179 o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */
1180 }
974 o(0xE92D5800); /* save fp, ip, lr */1181 o(0xE92D5800); /* save fp, ip, lr */
975 o(0xE28DB00C); /* add fp, sp, #12 */1182 o(0xE28DB00C); /* add fp, sp, #12 */
976 func_sub_sp_offset = ind;1183 func_sub_sp_offset = ind;
977 o(0xE1A00000); /* nop, leave space for stack adjustment */1184 o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */
978 while ((sym = sym->next)) {1185 {
979 CType *type;1186 int addr, pn = struct_ret, sn = 0; /* pn=core, sn=stack */
980 type = &sym->type;1187
981 size = type_size(type, &align);1188#ifdef TCC_ARM_HARDFLOAT
982 size = (size + 3) & -4;1189 avregs = AVAIL_REGS_INITIALIZER;
1190#endif
1191 while ((sym = sym->next)) {
1192 CType *type;
1193 type = &sym->type;
1194 size = type_size(type, &align);
1195 size = (size + 3) >> 2;
1196#ifdef TCC_ARM_HARDFLOAT
1197 if (!variadic && (is_float(sym->type.t)
1198 || is_float_hgen_aggr(&sym->type))) {
1199 int fpn = assign_fpreg(&avregs, align, size << 2);
1200 if (fpn >= 0) {
1201 addr = fpn * 4;
1202 } else
1203 goto from_stack;
1204 } else
1205#endif
1206 if (pn < 4) {
1207#ifdef TCC_ARM_EABI
1208 pn = (pn + (align-1)/4) & -(align/4);
1209#endif
1210 addr = (nf + pn) * 4;
1211 pn += size;
1212 if (!sn && pn > 4)
1213 sn = (pn - 4);
1214 } else {
1215#ifdef TCC_ARM_HARDFLOAT
1216from_stack:
1217#endif
983#ifdef TCC_ARM_EABI1218#ifdef TCC_ARM_EABI
984 addr = (addr + align - 1) & -align;1219 sn = (sn + (align-1)/4) & -(align/4);
985#endif1220#endif
986 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);1221 addr = (n + nf + sn) * 4;
987 addr += size;1222 sn += size;
1223 }
1224 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
1225 }
988 }1226 }
989 last_itod_magic=0;1227 last_itod_magic=0;
990 leaffunc = 1;1228 leaffunc = 1;
@@ -997,6 +1235,8 @@ void gfunc_epilog(void) · 6 unmodified lines
997 uint32_t x;1235 uint32_t x;
998 int diff;1236 int diff;
999#ifdef TCC_ARM_EABI1237#ifdef TCC_ARM_EABI
1238 /* Useless but harmless copy of the float result into main register(s) in case
1239 of variadic function in the hardfloat variant */
1000 if(is_float(func_vt.t)) {1240 if(is_float(func_vt.t)) {
1001 if((func_vt.t & VT_BTYPE) == VT_FLOAT)1241 if((func_vt.t & VT_BTYPE) == VT_FLOAT)
1002 o(0xEE100A10); /* fmrs r0, s0 */1242 o(0xEE100A10); /* fmrs r0, s0 */
tcc.h+3−0
@@ -204,6 +204,8 @@ · 203 unmodified lines
204# define CONFIG_TCC_ELFINTERP "/libexec/ld-elf.so.1"204# define CONFIG_TCC_ELFINTERP "/libexec/ld-elf.so.1"
205# elif defined __FreeBSD_kernel__205# elif defined __FreeBSD_kernel__
206# define CONFIG_TCC_ELFINTERP "/lib/ld.so.1"206# define CONFIG_TCC_ELFINTERP "/lib/ld.so.1"
207# elif defined TCC_ARM_HARDFLOAT
208# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-armhf.so.3"
207# elif defined TCC_ARM_EABI209# elif defined TCC_ARM_EABI
208# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3"210# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3"
209# elif defined(TCC_TARGET_X86_64)211# elif defined(TCC_TARGET_X86_64)
@@ -1138,6 +1140,7 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r); · 928 unmodified lines
1138ST_FUNC void vset(CType *type, int r, int v);1140ST_FUNC void vset(CType *type, int r, int v);
1139ST_FUNC void vswap(void);1141ST_FUNC void vswap(void);
1140ST_FUNC void vpush_global_sym(CType *type, int v);1142ST_FUNC void vpush_global_sym(CType *type, int v);
1143ST_FUNC void vrote(SValue *e, int n);
1141ST_FUNC void vrott(int n);1144ST_FUNC void vrott(int n);
1142ST_FUNC void vrotb(int n);1145ST_FUNC void vrotb(int n);
1143#ifdef TCC_TARGET_ARM1146#ifdef TCC_TARGET_ARM
tccgen.c+14−6
@@ -972,18 +972,26 @@ ST_FUNC void vrotb(int n) · 971 unmodified lines
972 vtop[0] = tmp;972 vtop[0] = tmp;
973}973}
974 974
975/* rotate n first stack elements to the top 975/* rotate the n elements before entry e towards the top
976 I1 ... In -> In I1 ... I(n-1) [top is right]976 I1 ... In ... -> In I1 ... I(n-1) ... [top is right]
977 */977 */
978ST_FUNC void vrott(int n)978ST_FUNC void vrote(SValue *e, int n)
979{979{
980 int i;980 int i;
981 SValue tmp;981 SValue tmp;
982 982
983 tmp = vtop[0];983 tmp = *e;
984 for(i = 0;i < n - 1; i++)984 for(i = 0;i < n - 1; i++)
985 vtop[-i] = vtop[-i - 1];985 e[-i] = e[-i - 1];
986 vtop[-n + 1] = tmp;986 e[-n + 1] = tmp;
987}
988
989/* rotate n first stack elements to the top
990 I1 ... In -> In I1 ... I(n-1) [top is right]
991 */
992ST_FUNC void vrott(int n)
993{
994 vrote(vtop, n);
987}995}
988 996
989/* pop stack value */997/* pop stack value */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t