Browse Source

* added register type parameter to cgsize2subreg(), as the subreg can
depend on that (and correct a number of cases where this was wrong)
* set the correct subreg type for xmm x86_64 parameter registers
(resolved mantis #14067)

git-svn-id: trunk@13410 -

Jonas Maebe 16 years ago
parent
commit
34c985cfa6

+ 1 - 0
.gitattributes

@@ -9201,6 +9201,7 @@ tests/webtbs/tw14019.pp svneol=native#text/plain
 tests/webtbs/tw14020.pp svneol=native#text/plain
 tests/webtbs/tw14020.pp svneol=native#text/plain
 tests/webtbs/tw14020a.pp svneol=native#text/plain
 tests/webtbs/tw14020a.pp svneol=native#text/plain
 tests/webtbs/tw14040.pp svneol=native#text/plain
 tests/webtbs/tw14040.pp svneol=native#text/plain
+tests/webtbs/tw14067.pp svneol=native#text/plain
 tests/webtbs/tw1407.pp svneol=native#text/plain
 tests/webtbs/tw1407.pp svneol=native#text/plain
 tests/webtbs/tw1408.pp svneol=native#text/plain
 tests/webtbs/tw1408.pp svneol=native#text/plain
 tests/webtbs/tw1409.pp svneol=native#text/plain
 tests/webtbs/tw1409.pp svneol=native#text/plain

+ 2 - 2
compiler/arm/cpubase.pas

@@ -354,7 +354,7 @@ unit cpubase;
 
 
     { Returns the tcgsize corresponding with the size of reg.}
     { Returns the tcgsize corresponding with the size of reg.}
     function reg_cgsize(const reg: tregister) : tcgsize;
     function reg_cgsize(const reg: tregister) : tcgsize;
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
     function is_calljmp(o:tasmop):boolean;
     function is_calljmp(o:tasmop):boolean;
     procedure inverse_flags(var f: TResFlags);
     procedure inverse_flags(var f: TResFlags);
     function flags_to_cond(const f: TResFlags) : TAsmCond;
     function flags_to_cond(const f: TResFlags) : TAsmCond;
@@ -391,7 +391,7 @@ unit cpubase;
       );
       );
 
 
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
       begin
         cgsize2subreg:=R_SUBWHOLE;
         cgsize2subreg:=R_SUBWHOLE;
       end;
       end;

+ 2 - 2
compiler/avr/cpubase.pas

@@ -332,7 +332,7 @@ unit cpubase;
 
 
     { Returns the tcgsize corresponding with the size of reg.}
     { Returns the tcgsize corresponding with the size of reg.}
     function reg_cgsize(const reg: tregister) : tcgsize;
     function reg_cgsize(const reg: tregister) : tcgsize;
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
     procedure inverse_flags(var f: TResFlags);
     procedure inverse_flags(var f: TResFlags);
     function flags_to_cond(const f: TResFlags) : TAsmCond;
     function flags_to_cond(const f: TResFlags) : TAsmCond;
     function findreg_by_number(r:Tregister):tregisterindex;
     function findreg_by_number(r:Tregister):tregisterindex;
@@ -367,7 +367,7 @@ unit cpubase;
       );
       );
 
 
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
       begin
         cgsize2subreg:=R_SUBWHOLE;
         cgsize2subreg:=R_SUBWHOLE;
       end;
       end;

+ 4 - 4
compiler/cgobj.pas

@@ -638,7 +638,7 @@ implementation
       begin
       begin
         if not assigned(rg[R_INTREGISTER]) then
         if not assigned(rg[R_INTREGISTER]) then
           internalerror(200312122);
           internalerror(200312122);
-        result:=rg[R_INTREGISTER].getregister(list,cgsize2subreg(size));
+        result:=rg[R_INTREGISTER].getregister(list,cgsize2subreg(R_INTREGISTER,size));
       end;
       end;
 
 
 
 
@@ -646,7 +646,7 @@ implementation
       begin
       begin
         if not assigned(rg[R_FPUREGISTER]) then
         if not assigned(rg[R_FPUREGISTER]) then
           internalerror(200312123);
           internalerror(200312123);
-        result:=rg[R_FPUREGISTER].getregister(list,cgsize2subreg(size));
+        result:=rg[R_FPUREGISTER].getregister(list,cgsize2subreg(R_FPUREGISTER,size));
       end;
       end;
 
 
 
 
@@ -654,7 +654,7 @@ implementation
       begin
       begin
         if not assigned(rg[R_MMREGISTER]) then
         if not assigned(rg[R_MMREGISTER]) then
           internalerror(2003121214);
           internalerror(2003121214);
-        result:=rg[R_MMREGISTER].getregister(list,cgsize2subreg(size));
+        result:=rg[R_MMREGISTER].getregister(list,cgsize2subreg(R_MMREGISTER,size));
       end;
       end;
 
 
 
 
@@ -675,7 +675,7 @@ implementation
       var
       var
         subreg:Tsubregister;
         subreg:Tsubregister;
       begin
       begin
-        subreg:=cgsize2subreg(size);
+        subreg:=cgsize2subreg(getregtype(reg),size);
         result:=reg;
         result:=reg;
         setsubreg(result,subreg);
         setsubreg(result,subreg);
         { notify RA }
         { notify RA }

+ 2 - 2
compiler/m68k/cpubase.pas

@@ -328,7 +328,7 @@ unit cpubase;
 
 
     procedure inverse_flags(var r : TResFlags);
     procedure inverse_flags(var r : TResFlags);
     function  flags_to_cond(const f: TResFlags) : TAsmCond;
     function  flags_to_cond(const f: TResFlags) : TAsmCond;
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
     function reg_cgsize(const reg: tregister): tcgsize;
     function reg_cgsize(const reg: tregister): tcgsize;
 
 
     function findreg_by_number(r:Tregister):tregisterindex;
     function findreg_by_number(r:Tregister):tregisterindex;
@@ -407,7 +407,7 @@ implementation
         flags_to_cond := flags2cond[f];
         flags_to_cond := flags2cond[f];
       end;
       end;
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       var p: pointer;
       var p: pointer;
       begin
       begin
         case s of
         case s of

+ 2 - 2
compiler/m68k/cpupara.pas

@@ -247,9 +247,9 @@ unit cpupara;
                p.funcretloc[side].loc:=LOC_REGISTER;
                p.funcretloc[side].loc:=LOC_REGISTER;
                p.funcretloc[side].size:=retcgsize;
                p.funcretloc[side].size:=retcgsize;
                if side=callerside then
                if side=callerside then
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
              end;
              end;
           end;
           end;
       end;
       end;

+ 2 - 2
compiler/powerpc/cpubase.pas

@@ -395,7 +395,7 @@ uses
     procedure create_cond_imm(BO,BI:byte;var r : TAsmCond);
     procedure create_cond_imm(BO,BI:byte;var r : TAsmCond);
     procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
     procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
     { Returns the tcgsize corresponding with the size of reg.}
     { Returns the tcgsize corresponding with the size of reg.}
     function reg_cgsize(const reg: tregister) : tcgsize;
     function reg_cgsize(const reg: tregister) : tcgsize;
 
 
@@ -535,7 +535,7 @@ implementation
       end;
       end;
 
 
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
       begin
         cgsize2subreg:=R_SUBWHOLE;
         cgsize2subreg:=R_SUBWHOLE;
       end;
       end;

+ 2 - 2
compiler/powerpc/cpupara.pas

@@ -300,9 +300,9 @@ unit cpupara;
                p.funcretloc[side].loc:=LOC_REGISTER;
                p.funcretloc[side].loc:=LOC_REGISTER;
                p.funcretloc[side].size:=retcgsize;
                p.funcretloc[side].size:=retcgsize;
                if side=callerside then
                if side=callerside then
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
              end;
              end;
           end;
           end;
       end;
       end;

+ 2 - 2
compiler/powerpc64/cpubase.pas

@@ -398,7 +398,7 @@ function flags_to_cond(const f: TResFlags): TAsmCond;
 procedure create_cond_imm(BO, BI: byte; var r: TAsmCond);
 procedure create_cond_imm(BO, BI: byte; var r: TAsmCond);
 procedure create_cond_norm(cond: TAsmCondFlag; cr: byte; var r: TasmCond);
 procedure create_cond_norm(cond: TAsmCondFlag; cr: byte; var r: TasmCond);
 
 
-function cgsize2subreg(s: Tcgsize): Tsubregister;
+function cgsize2subreg(regtype: tregistertype; s: Tcgsize): Tsubregister;
 { Returns the tcgsize corresponding with the size of reg.}
 { Returns the tcgsize corresponding with the size of reg.}
 function reg_cgsize(const reg: tregister): tcgsize;
 function reg_cgsize(const reg: tregister): tcgsize;
 
 
@@ -533,7 +533,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-function cgsize2subreg(s: Tcgsize): Tsubregister;
+function cgsize2subreg(regtype: tregistertype; s: Tcgsize): Tsubregister;
 begin
 begin
   cgsize2subreg := R_SUBWHOLE;
   cgsize2subreg := R_SUBWHOLE;
 end;
 end;

+ 2 - 2
compiler/powerpc64/cpupara.pas

@@ -239,10 +239,10 @@ begin
       p.funcretloc[side].size := retcgsize;
       p.funcretloc[side].size := retcgsize;
       if side = callerside then
       if side = callerside then
         p.funcretloc[side].register := newreg(R_INTREGISTER,
         p.funcretloc[side].register := newreg(R_INTREGISTER,
-          RS_FUNCTION_RESULT_REG, cgsize2subreg(retcgsize))
+          RS_FUNCTION_RESULT_REG, cgsize2subreg(R_INTREGISTER, retcgsize))
       else
       else
         p.funcretloc[side].register := newreg(R_INTREGISTER,
         p.funcretloc[side].register := newreg(R_INTREGISTER,
-          RS_FUNCTION_RETURN_REG, cgsize2subreg(retcgsize));
+          RS_FUNCTION_RETURN_REG, cgsize2subreg(R_INTREGISTER, retcgsize));
     end;
     end;
 end;
 end;
 
 

+ 22 - 6
compiler/sparc/cpubase.pas

@@ -336,7 +336,7 @@ uses
     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
 
 
     function  flags_to_cond(const f: TResFlags) : TAsmCond;
     function  flags_to_cond(const f: TResFlags) : TAsmCond;
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
     function reg_cgsize(const reg: tregister): tcgsize;
     function reg_cgsize(const reg: tregister): tcgsize;
     function std_regname(r:Tregister):string;
     function std_regname(r:Tregister):string;
     function std_regnum_search(const s:string):Tregister;
     function std_regnum_search(const s:string):Tregister;
@@ -395,12 +395,28 @@ implementation
       end;
       end;
 
 
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
       begin
-        if s in [OS_64,OS_S64] then
-          cgsize2subreg:=R_SUBQ
-        else
-          cgsize2subreg:=R_SUBWHOLE;
+        case regtype of
+          R_FPUREGISTER:
+            case s of
+              OS_F32:
+                cgsize2subreg:=R_SUBFS;
+              OS_F64:
+                cgsize2subreg:=R_SUBFD;
+              OS_F128:
+                cgsize2subreg:=R_SUBFQ;
+              else
+                internalerror(2009071903);
+            end;
+          else
+            begin
+              if s in [OS_64,OS_S64] then
+                cgsize2subreg:=R_SUBQ
+              else
+                cgsize2subreg:=R_SUBWHOLE;
+            end;
+        end;
       end;
       end;
 
 
 
 

+ 2 - 2
compiler/sparc/cpupara.pas

@@ -196,9 +196,9 @@ implementation
                p.funcretloc[side].loc:=LOC_REGISTER;
                p.funcretloc[side].loc:=LOC_REGISTER;
                p.funcretloc[side].size:=retcgsize;
                p.funcretloc[side].size:=retcgsize;
                if (side=callerside) then
                if (side=callerside) then
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
              end;
              end;
           end;
           end;
       end;
       end;

+ 19 - 4
compiler/x86/cpubase.pas

@@ -244,7 +244,7 @@ uses
                                   Helpers
                                   Helpers
 *****************************************************************************}
 *****************************************************************************}
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
     function reg2opsize(r:Tregister):topsize;
     function reg2opsize(r:Tregister):topsize;
     function reg_cgsize(const reg: tregister): tcgsize;
     function reg_cgsize(const reg: tregister): tcgsize;
     function is_calljmp(o:tasmop):boolean;
     function is_calljmp(o:tasmop):boolean;
@@ -295,7 +295,7 @@ implementation
                                   Helpers
                                   Helpers
 *****************************************************************************}
 *****************************************************************************}
 
 
-    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
       begin
         case s of
         case s of
           OS_8,OS_S8:
           OS_8,OS_S8:
@@ -308,9 +308,24 @@ implementation
             cgsize2subreg:=R_SUBQ;
             cgsize2subreg:=R_SUBQ;
           OS_M64:
           OS_M64:
             cgsize2subreg:=R_SUBNONE;
             cgsize2subreg:=R_SUBNONE;
-          OS_F32,OS_F64,OS_C64,
+          OS_F32,OS_F64,OS_C64:
+            case regtype of
+              R_FPUREGISTER:
+                cgsize2subreg:=R_SUBWHOLE;
+              R_MMREGISTER:
+                case s of
+                  OS_F32:
+                    cgsize2subreg:=R_SUBMMS;
+                  OS_F64:
+                    cgsize2subreg:=R_SUBMMD;
+                  else
+                    internalerror(2009071901);
+                end;
+              else
+                internalerror(2009071902);
+            end;
           OS_M128,OS_MS128:
           OS_M128,OS_MS128:
-            cgsize2subreg:=R_SUBWHOLE;
+            cgsize2subreg:=R_SUBMMWHOLE;
           else
           else
             internalerror(200301231);
             internalerror(200301231);
         end;
         end;

+ 14 - 5
compiler/x86_64/cpupara.pas

@@ -472,9 +472,9 @@ unit cpupara;
               begin
               begin
                 p.funcretloc[side].size:=retcgsize;
                 p.funcretloc[side].size:=retcgsize;
                 if side=callerside then
                 if side=callerside then
-                  p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+                  p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                 else
                 else
-                  p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+                  p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
               end;
               end;
           end;
           end;
       end;
       end;
@@ -577,7 +577,7 @@ unit cpupara;
                               { s64comp is pushed in an int register }
                               { s64comp is pushed in an int register }
                               if paraloc^.size=OS_C64 then
                               if paraloc^.size=OS_C64 then
                                 paraloc^.size:=OS_64;
                                 paraloc^.size:=OS_64;
-                              subreg:=cgsize2subreg(paraloc^.size);
+                              subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
                             end;
                             end;
 
 
                           { winx64 uses different registers }
                           { winx64 uses different registers }
@@ -598,11 +598,20 @@ unit cpupara;
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc^.loc:=LOC_MMREGISTER;
                           paraloc^.loc:=LOC_MMREGISTER;
 
 
+                          case paracgsize of
+                            OS_F32:
+                              subreg:=R_SUBMMS;
+                            OS_F64:
+                              subreg:=R_SUBMMD;
+                            else
+                              subreg:=R_SUBMMWHOLE;
+                          end;
+
                           { winx64 uses different registers }
                           { winx64 uses different registers }
                           if target_info.system=system_x86_64_win64 then
                           if target_info.system=system_x86_64_win64 then
-                            paraloc^.register:=newreg(R_MMREGISTER,parammsupregs_winx64[mmparareg],R_SUBNONE)
+                            paraloc^.register:=newreg(R_MMREGISTER,parammsupregs_winx64[mmparareg],subreg)
                           else
                           else
-                            paraloc^.register:=newreg(R_MMREGISTER,parammsupregs[mmparareg],R_SUBNONE);
+                            paraloc^.register:=newreg(R_MMREGISTER,parammsupregs[mmparareg],subreg);
                           if paracgsize=OS_F128 then
                           if paracgsize=OS_F128 then
                             paraloc^.size:=OS_F64
                             paraloc^.size:=OS_F64
                           else
                           else

+ 61 - 0
tests/webtbs/tw14067.pp

@@ -0,0 +1,61 @@
+{ %cpu=x86_64 }
+{ %interactive }
+
+{ check the assembler file for superfluous register moves from/to the
+  parameter xmm regs }
+
+program disasm;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, SysUtils
+  { you can add units after this };
+
+(*procedure ProcReg(A: Int64; B: Int64; C: Int64; D: Int64; E, F, G, H: Int64); register;
+begin
+
+end;
+
+procedure ProcStd(A: Int64; B: Int64; C: Int64; D: Int64; E, F, G, H: Int64); stdcall;
+begin
+
+end;*)
+
+procedure ProcFReg(A, B, C, D, E, F, G, H: Double); register;
+begin
+
+end;
+
+procedure ProcFStd(A, B, C, D, E, F, G, H: Double); stdcall;
+begin
+
+end;
+
+begin
+  (*asm
+    push %R8
+    pop %R8
+  end;
+  ProcReg($10, $20, $30, $40, $50, $60, $70, $80);
+  asm
+    push %R8
+    pop %R8
+  end;
+  ProcStd($10, $20, $30, $40, $50, $60, $70, $80);
+  asm
+    push %R8
+    pop %R8
+  end;
+  ProcFReg(0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80);
+  asm
+    push %R8
+    pop %R8
+  end;                                                     *)
+  ProcFStd(0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80);
+  (*asm
+    push %R8
+    pop %R8
+  end;*)
+end.
+