Browse Source

* refactored the int64 result passing in ax:bx:cx:dx to use 4 paralocs, instead of the GetNextReg hack

git-svn-id: trunk@24527 -
nickysn 12 năm trước cách đây
mục cha
commit
ecb5a4866d
4 tập tin đã thay đổi với 139 bổ sung41 xóa
  1. 63 7
      compiler/cg64f32.pas
  2. 22 4
      compiler/i8086/cpupara.pas
  3. 54 20
      compiler/ncgutil.pas
  4. 0 10
      compiler/x86/cpubase.pas

+ 63 - 7
compiler/cg64f32.pas

@@ -122,8 +122,8 @@ unit cg64f32;
 
     procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
       var
-        paraloclo,
-        paralochi : pcgparalocation;
+        paraloclo,paraloclo2,
+        paralochi,paralochi2 : pcgparalocation;
       begin
         if not(cgpara.size in [OS_64,OS_S64]) then
           internalerror(200408231);
@@ -143,6 +143,55 @@ unit cg64f32;
         cgparalo.intsize:=4;
         cgparalo.alignment:=cgpara.alignment;
         paraloclo:=cgparalo.add_location;
+        { 4 parameter fields? }
+        if assigned(cgpara.location^.next) and assigned(cgpara.location^.next^.next) and assigned(cgpara.location^.next^.next^.next) then
+          begin
+            { Order for multiple locations is always
+                paraloc^ -> high
+                paraloc^.next -> low }
+            if (target_info.endian=ENDIAN_BIG) then
+              begin
+                { paraloc^ -> high }
+                move(cgpara.location^,paralochi^,sizeof(paralochi^));
+                paralochi^.next:=nil;
+                paralochi2:=cgparahi.add_location;
+                move(cgpara.location^.next,paralochi2^,sizeof(paralochi2^));
+
+                { paraloc^.next^.next^ -> low }
+                move(cgpara.location^.next^.next^,paraloclo^,sizeof(paraloclo^));
+                paraloclo^.next:=nil;
+                paraloclo2:=cgparalo.add_location;
+                move(cgpara.location^.next^.next^.next^,paraloclo2^,sizeof(paraloclo2^));
+              end
+            else
+              begin
+                { paraloc^ -> low }
+                move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+                paraloclo^.next:=nil;
+                paraloclo2:=cgparalo.add_location;
+                move(cgpara.location^.next^,paraloclo2^,sizeof(paraloclo2^));
+
+                { paraloc^.next^.next -> high }
+                move(cgpara.location^.next^.next^,paralochi^,sizeof(paralochi^));
+                paralochi^.next:=nil;
+                paralochi2:=cgparahi.add_location;
+                move(cgpara.location^.next^.next^.next^,paralochi2^,sizeof(paralochi2^));
+              end;
+
+            { fix size }
+            paraloclo^.size:=OS_16;
+            paraloclo2^.size:=OS_16;
+            paraloclo2^.next:=nil;
+            paralochi^.size:=OS_16;
+            paralochi2^.size:=OS_16;
+            paralochi2^.next:=nil;
+            if cgpara.size=OS_S64 then
+              if target_info.endian=ENDIAN_BIG then
+                paralochi^.size:=OS_S16
+              else
+                paraloclo2^.size:=OS_S16;
+          end
+        else
         { 2 parameter fields? }
         if assigned(cgpara.location^.next) then
           begin
@@ -163,6 +212,12 @@ unit cg64f32;
                 move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
                 move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
               end;
+
+            { fix size }
+            paraloclo^.size:=cgparalo.size;
+            paraloclo^.next:=nil;
+            paralochi^.size:=cgparahi.size;
+            paralochi^.next:=nil;
           end
         else
           begin
@@ -182,12 +237,13 @@ unit cg64f32;
                 inc(cgparahi.location^.reference.offset,4);
                 cgparahi.alignment:=newalignment(cgparahi.alignment,4);
               end;
+
+            { fix size }
+            paraloclo^.size:=cgparalo.size;
+            paraloclo^.next:=nil;
+            paralochi^.size:=cgparahi.size;
+            paralochi^.next:=nil;
           end;
-        { fix size }
-        paraloclo^.size:=cgparalo.size;
-        paraloclo^.next:=nil;
-        paralochi^.size:=cgparahi.size;
-        paralochi^.next:=nil;
       end;
 
 

+ 22 - 4
compiler/i8086/cpupara.pas

@@ -329,21 +329,39 @@ unit cpupara;
             paraloc^.loc:=LOC_REGISTER;
             if retcgsize in [OS_64,OS_S64] then
              begin
-               { low 32bits }
+               { bits 0..15 }
                if side=callerside then
                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
-               paraloc^.size:=OS_32;
+               paraloc^.size:=OS_16;
+
+               { bits 16..31 }
+               paraloc:=result.add_location;
+               paraloc^.loc:=LOC_REGISTER;
+               if side=callerside then
+                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+               else
+                 paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+               paraloc^.size:=OS_16;
 
-               { high 32bits }
+               { bits 32..47 }
                paraloc:=result.add_location;
                paraloc^.loc:=LOC_REGISTER;
                if side=callerside then
                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGHER_REG
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
-               paraloc^.size:=OS_32;
+               paraloc^.size:=OS_16;
+
+               { bits 48..63 }
+               paraloc:=result.add_location;
+               paraloc^.loc:=LOC_REGISTER;
+               if side=callerside then
+                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGHEST_REG
+               else
+                 paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
+               paraloc^.size:=OS_16;
              end
             else if retcgsize in [OS_32,OS_S32] then
              begin

+ 54 - 20
compiler/ncgutil.pas

@@ -1002,27 +1002,61 @@ implementation
                       begin
                         if not assigned(paraloc^.next) then
                           internalerror(200410104);
-                        if (target_info.endian=ENDIAN_BIG) then
-                          begin
-                            { paraloc^ -> high
-                              paraloc^.next -> low }
-                            unget_para(paraloc^);
-                            gen_alloc_regloc(list,destloc);
-                            { reg->reg, alignment is irrelevant }
-                            cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reghi,4);
-                            unget_para(paraloc^.next^);
-                            cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
-                          end
+{$ifdef cpu16bitalu}
+                        { 4 paralocs? }
+                        if assigned(paraloc^.next) and assigned(paraloc^.next^.next) and assigned(paraloc^.next^.next^.next) then
+                          if (target_info.endian=ENDIAN_BIG) then
+                            begin
+                              { paraloc^ -> high
+                                paraloc^.next^.next -> low }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc);
+                              { reg->reg, alignment is irrelevant }
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,GetNextReg(destloc.register64.reghi),2);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,destloc.register64.reghi,2);
+                              unget_para(paraloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,GetNextReg(destloc.register64.reglo),2);
+                              unget_para(paraloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,destloc.register64.reglo,2);
+                            end
+                          else
+                            begin
+                              { paraloc^ -> low
+                                paraloc^.next^.next -> high }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,destloc.register64.reglo,2);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,GetNextReg(destloc.register64.reglo),2);
+                              unget_para(paraloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,destloc.register64.reghi,2);
+                              unget_para(paraloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,GetNextReg(destloc.register64.reghi),2);
+                            end
                         else
-                          begin
-                            { paraloc^ -> low
-                              paraloc^.next -> high }
-                            unget_para(paraloc^);
-                            gen_alloc_regloc(list,destloc);
-                            cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
-                            unget_para(paraloc^.next^);
-                            cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
-                          end;
+{$endif cpu16bitalu}
+                          if (target_info.endian=ENDIAN_BIG) then
+                            begin
+                              { paraloc^ -> high
+                                paraloc^.next -> low }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc);
+                              { reg->reg, alignment is irrelevant }
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reghi,4);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
+                            end
+                          else
+                            begin
+                              { paraloc^ -> low
+                                paraloc^.next -> high }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc);
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
+                            end;
                       end;
                     LOC_REFERENCE:
                       begin

+ 0 - 10
compiler/x86/cpubase.pas

@@ -556,16 +556,6 @@ implementation
 {$ifdef i8086}
     function GetNextReg(const r: TRegister): TRegister;
       begin
-        { HACK for returning 64-bit values in registers ax:bx:cx:dx }
-        case r of
-          NR_FUNCTION_RESULT64_LOW_REG: exit(NR_FUNCTION_RESULT64_HIGH_REG);
-          NR_FUNCTION_RESULT64_HIGHER_REG: exit(NR_FUNCTION_RESULT64_HIGHEST_REG);
-        end;
-        case r of
-          NR_FUNCTION_RETURN64_LOW_REG: exit(NR_FUNCTION_RETURN64_HIGH_REG);
-          NR_FUNCTION_RETURN64_HIGHER_REG: exit(NR_FUNCTION_RETURN64_HIGHEST_REG);
-        end;
-
         if getsupreg(r)<first_int_imreg then
           internalerror(2013051401);
         result:=TRegister(longint(r)+1);