History

Fix allocation of struct in registers on ARM

Allocation of struct in core and/or VFP registers on ARM is made by manipulating the value stack to create 3 distinct zones: parameters allocated on stack, parameters of type struct allocated in core registers and parameters of type struct allocated in VFP registers. Parameters of primitive type can be in any zone. This commit change the order of the zones from stack, VFP, core to stack, core, VFP (from highest addresses to lowest ones) in order to correctly deal the situation when structures are allocated both in core and VFP registers.

Thomas Preud'homme committed 13 years ago

Commit b7d017d1 parent cf02f921 file · +44 −46Browse files

Unified · Split

arm-gen.c+44−46
@@ -826,7 +826,7 @@ void gfunc_call(int nb_args) · 825 unmodified lines
826 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno;826 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno;
827 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};827 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
828 SValue *before_stack = NULL; /* SValue before first on stack argument */828 SValue *before_stack = NULL; /* SValue before first on stack argument */
829 SValue *before_vfpreg_hfa = NULL; /* SValue before first in VFP reg hfa argument */829 SValue *before_creg = NULL; /* SValue before first argument of type struct in core register */
830#ifdef TCC_ARM_HARDFLOAT830#ifdef TCC_ARM_HARDFLOAT
831 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;831 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
832 signed char vfp_plan[16];832 signed char vfp_plan[16];
@@ -865,12 +865,12 @@ void gfunc_call(int nb_args) · 32 unmodified lines
865 (core or VFP) are free for the current argument, assign them to it, else865 (core or VFP) are free for the current argument, assign them to it, else
866 allocate on stack with correct alignment. Whenever a structure is allocated866 allocate on stack with correct alignment. Whenever a structure is allocated
867 in registers or on stack, it is always put on the stack at this stage. The867 in registers or on stack, it is always put on the stack at this stage. The
868 stack is divided in 3 zones. The zone are, from low addresses to high868 stack is divided in 3 zones. The zone are, from high addresses to low
869 addresses: structures to be loaded in core registers, structures to be869 addresses: structures to be loaded in core registers, structures to be
870 loaded in VFP registers, argument allocated to stack. SValue's representing870 loaded in VFP registers, argument allocated to stack. SValue's representing
871 structures in the first zone are moved just after the SValue pointed by871 structures in the first zone are moved just after the SValue pointed by
872 before_vfpreg_hfa. SValue's representing structures in the second zone are872 before_stack. SValue's representing structures in the second zone are
873 moved just after the SValue pointer by before_stack. */873 moved just after the SValue pointer by before_creg. */
874 for(i = nb_args; i-- ;) {874 for(i = nb_args; i-- ;) {
875 int j, assigned_vfpreg = 0;875 int j, assigned_vfpreg = 0;
876 size = type_size(&vtop[-i].type, &align);876 size = type_size(&vtop[-i].type, &align);
@@ -892,14 +892,15 @@ void gfunc_call(int nb_args) · 15 unmodified lines
892 if (assigned_vfpreg >= 0) {892 if (assigned_vfpreg >= 0) {
893 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2;893 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2;
894 if (hfa) {894 if (hfa) {
895 /* before_stack can only have been set because all core registers895 /* if before_creg is not set, it means that no parameter has been
896 are assigned, so no need to care about before_vfpreg_hfa if896 * allocated in core register. This implied that no argument has
897 before_stack is set */897 * been allocated on stack neither because a VFP was available for
898 if (before_stack) {898 * this parameter. */
899 vrote(&vtop[-i], &vtop[-i] - before_stack);899 if (before_creg) {
900 before_stack++;900 /* before_creg already exists and we just update it */
901 } else if (!before_vfpreg_hfa)901 vrote(&vtop[-i], &vtop[-i] - before_creg);
902 before_vfpreg_hfa = &vtop[-i-1];902 before_creg++;
903 }
903 for (j = assigned_vfpreg; j <= end_reg; j++)904 for (j = assigned_vfpreg; j <= end_reg; j++)
904 vfp_todo|=(1<<j);905 vfp_todo|=(1<<j);
905 }906 }
@@ -907,10 +908,8 @@ void gfunc_call(int nb_args) · 1 unmodified line
907 } else {908 } else {
908 if (!hfa)909 if (!hfa)
909 vfp_argno++;910 vfp_argno++;
910 /* No need to update before_stack as no more hfa can be allocated in911 if (!before_stack)
911 VFP regs */912 before_stack = &vtop[-i-1];
912 if (!before_vfpreg_hfa)
913 before_vfpreg_hfa = &vtop[-i-1];
914 break;913 break;
915 }914 }
916 }915 }
@@ -919,14 +918,14 @@ void gfunc_call(int nb_args) · 2 unmodified lines
919 ncrn = (ncrn + (align-1)/4) & -(align/4);918 ncrn = (ncrn + (align-1)/4) & -(align/4);
920 size = (size + 3) & -4;919 size = (size + 3) & -4;
921 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) {920 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) {
922 /* Either there is HFA in VFP registers, or there is arguments on stack,921 if (before_stack) {
923 it cannot be both. Hence either before_stack already points after922 vrote(&vtop[-i], &vtop[-i] - before_stack);
924 the slot where the vtop[-i] SValue is moved, or before_stack will not923 before_stack++;
925 be used */924 /* before_stack can only have been set because all VFP registers are
926 if (before_vfpreg_hfa) {925 * assigned, so no need to care about before_creg if before_stack is
927 vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa);926 * set since no more argument will be allocated in a VFP register. */
928 before_vfpreg_hfa++;927 } else if (!before_creg)
929 }928 before_creg = &vtop[-i];
930 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)929 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
931 todo|=(1<<j);930 todo|=(1<<j);
932 ncrn+=size/4;931 ncrn+=size/4;
@@ -935,11 +934,10 @@ void gfunc_call(int nb_args) · 2 unmodified lines
935 if (!before_stack)934 if (!before_stack)
936 before_stack = &vtop[-i-1];935 before_stack = &vtop[-i-1];
937 }936 }
938 }937 } else {
939 else {
940 ncrn = 4;938 ncrn = 4;
941 /* No need to set before_vfpreg_hfa if not set since there will no939 /* No need to set before_creg since it has already been set when
942 longer be any structure assigned to core registers */940 * assigning argument to core registers */
943 if (!before_stack)941 if (!before_stack)
944 before_stack = &vtop[-i-1];942 before_stack = &vtop[-i-1];
945 break;943 break;
@@ -1092,24 +1090,6 @@ void gfunc_call(int nb_args) · 146 unmodified lines
1092 }1090 }
1093save_regs(keep); /* save used temporary registers */1091save_regs(keep); /* save used temporary registers */
1094 keep++;1092 keep++;
1095 if(ncrn) {
1096 int nb_regs=0;
1097 if (ncrn>4)
1098 ncrn=4;
1099 todo&=((1<<ncrn)-1);
1100 if(todo) {
1101 int i;
1102 o(0xE8BD0000|todo);
1103 for(i=0;i<4;i++)
1104 if(todo&(1<<i)) {
1105 vpushi(0);
1106 vtop->r=i;
1107 keep++;
1108 nb_regs++;
1109 }
1110 }
1111 args_size-=nb_regs*4;
1112 }
1113 if(vfp_todo) {1093 if(vfp_todo) {
1114 int nb_fregs=0;1094 int nb_fregs=0;
1115 1095
@@ -1129,6 +1109,24 @@ save_regs(keep); /* save used temporary registers */ · 13 unmodified lines
1129 args_size-=nb_fregs*4;1109 args_size-=nb_fregs*4;
1130 }1110 }
1131 }1111 }
1112 if(ncrn) {
1113 int nb_regs=0;
1114 if (ncrn>4)
1115 ncrn=4;
1116 todo&=((1<<ncrn)-1);
1117 if(todo) {
1118 int i;
1119 o(0xE8BD0000|todo);
1120 for(i=0;i<4;i++)
1121 if(todo&(1<<i)) {
1122 vpushi(0);
1123 vtop->r=i;
1124 keep++;
1125 nb_regs++;
1126 }
1127 }
1128 args_size-=nb_regs*4;
1129 }
1132 vrotb(keep);1130 vrotb(keep);
1133 gcall_or_jmp(0);1131 gcall_or_jmp(0);
1134 if (args_size)1132 if (args_size)

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