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
826826 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno;
827827 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
828828 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 */
830830 #ifdef TCC_ARM_HARDFLOAT
831831 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
832832 signed char vfp_plan[16];
@@ -865,12 +865,12 @@ void gfunc_call(int nb_args) · 32 unmodified lines
865865 (core or VFP) are free for the current argument, assign them to it, else
866866 allocate on stack with correct alignment. Whenever a structure is allocated
867867 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 high
868+ stack is divided in 3 zones. The zone are, from high addresses to low
869869 addresses: structures to be loaded in core registers, structures to be
870870 loaded in VFP registers, argument allocated to stack. SValue's representing
871871 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 are
873− moved just after the SValue pointer by before_stack. */
872+ before_stack. SValue's representing structures in the second zone are
873+ moved just after the SValue pointer by before_creg. */
874874 for(i = nb_args; i-- ;) {
875875 int j, assigned_vfpreg = 0;
876876 size = type_size(&vtop[-i].type, &align);
@@ -892,14 +892,15 @@ void gfunc_call(int nb_args) · 15 unmodified lines
892892 if (assigned_vfpreg >= 0) {
893893 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2;
894894 if (hfa) {
895− /* before_stack can only have been set because all core registers
896− are assigned, so no need to care about before_vfpreg_hfa if
897− before_stack is set */
898− if (before_stack) {
899− vrote(&vtop[-i], &vtop[-i] - before_stack);
900− before_stack++;
901− } else if (!before_vfpreg_hfa)
902− before_vfpreg_hfa = &vtop[-i-1];
895+ /* if before_creg is not set, it means that no parameter has been
896+ * allocated in core register. This implied that no argument has
897+ * been allocated on stack neither because a VFP was available for
898+ * this parameter. */
899+ if (before_creg) {
900+ /* before_creg already exists and we just update it */
901+ vrote(&vtop[-i], &vtop[-i] - before_creg);
902+ before_creg++;
903+ }
903904 for (j = assigned_vfpreg; j <= end_reg; j++)
904905 vfp_todo|=(1<<j);
905906 }
@@ -907,10 +908,8 @@ void gfunc_call(int nb_args) · 1 unmodified line
907908 } else {
908909 if (!hfa)
909910 vfp_argno++;
910− /* No need to update before_stack as no more hfa can be allocated in
911− VFP regs */
912− if (!before_vfpreg_hfa)
913− before_vfpreg_hfa = &vtop[-i-1];
911+ if (!before_stack)
912+ before_stack = &vtop[-i-1];
914913 break;
915914 }
916915 }
@@ -919,14 +918,14 @@ void gfunc_call(int nb_args) · 2 unmodified lines
919918 ncrn = (ncrn + (align-1)/4) & -(align/4);
920919 size = (size + 3) & -4;
921920 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) {
922− /* Either there is HFA in VFP registers, or there is arguments on stack,
923− it cannot be both. Hence either before_stack already points after
924− the slot where the vtop[-i] SValue is moved, or before_stack will not
925− be used */
926− if (before_vfpreg_hfa) {
927− vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa);
928− before_vfpreg_hfa++;
929− }
921+ if (before_stack) {
922+ vrote(&vtop[-i], &vtop[-i] - before_stack);
923+ before_stack++;
924+ /* before_stack can only have been set because all VFP registers are
925+ * assigned, so no need to care about before_creg if before_stack is
926+ * set since no more argument will be allocated in a VFP register. */
927+ } else if (!before_creg)
928+ before_creg = &vtop[-i];
930929 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
931930 todo|=(1<<j);
932931 ncrn+=size/4;
@@ -935,11 +934,10 @@ void gfunc_call(int nb_args) · 2 unmodified lines
935934 if (!before_stack)
936935 before_stack = &vtop[-i-1];
937936 }
938− }
939− else {
937+ } else {
940938 ncrn = 4;
941− /* No need to set before_vfpreg_hfa if not set since there will no
942− longer be any structure assigned to core registers */
939+ /* No need to set before_creg since it has already been set when
940+ * assigning argument to core registers */
943941 if (!before_stack)
944942 before_stack = &vtop[-i-1];
945943 break;
@@ -1092,24 +1090,6 @@ void gfunc_call(int nb_args) · 146 unmodified lines
10921090 }
10931091 save_regs(keep); /* save used temporary registers */
10941092 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− }
11131093 if(vfp_todo) {
11141094 int nb_fregs=0;
11151095
@@ -1129,6 +1109,24 @@ save_regs(keep); /* save used temporary registers */ · 13 unmodified lines
11291109 args_size-=nb_fregs*4;
11301110 }
11311111 }
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+ }
11321130 vrotb(keep);
11331131 gcall_or_jmp(0);
11341132 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