Browse Source

* handle the fact that records containing a single extended value are
returned on the x87 fpu stack on x86-64
o also handle the fact that this means that we'll generated float
loads/stores with OS_128/OS_F128 in case the surrounding record
is padded to a multiple of its alignment

git-svn-id: trunk@28985 -

Jonas Maebe 10 years ago
parent
commit
d8c898742a
2 changed files with 39 additions and 0 deletions
  1. 27 0
      compiler/x86_64/cgcpu.pas
  2. 12 0
      compiler/x86_64/cpupara.pas

+ 27 - 0
compiler/x86_64/cgcpu.pas

@@ -36,6 +36,9 @@ unit cgcpu;
       tcgx86_64 = class(tcgx86)
       tcgx86_64 = class(tcgx86)
         procedure init_register_allocators;override;
         procedure init_register_allocators;override;
 
 
+        procedure a_loadfpu_ref_cgpara(list: TAsmList; size: tcgsize; const ref: treference; const cgpara: TCGPara); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
         procedure g_proc_entry(list : TAsmList;localsize:longint; nostackframe:boolean);override;
         procedure g_proc_entry(list : TAsmList;localsize:longint; nostackframe:boolean);override;
         procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
         procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
@@ -116,6 +119,30 @@ unit cgcpu;
       end;
       end;
 
 
 
 
+    procedure tcgx86_64.a_loadfpu_ref_cgpara(list: TAsmList; size: tcgsize; const ref: treference; const cgpara: TCGPara);
+      begin
+        { a record containing an extended value is returned on the x87 stack
+          -> size will be OS_F128 (if not packed), while cgpara.paraloc^.size
+          contains the proper size
+
+          In the future we should probably always use cgpara.location^.size, but
+          that should only be tested/done after 2.8 is branched }
+        if size in [OS_128,OS_F128] then
+          size:=cgpara.location^.size;
+        inherited;
+      end;
+
+
+    procedure tcgx86_64.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+      begin
+        { same as with a_loadfpu_ref_cgpara() above, but on the callee side
+          when the value is moved from the fpu register into a memory location }
+        if tosize in [OS_128,OS_F128] then
+          tosize:=OS_F80;
+        inherited;
+      end;
+
+
     function tcgx86_64.use_push: boolean;
     function tcgx86_64.use_push: boolean;
       begin
       begin
         result:=(current_procinfo.framepointer=NR_STACK_POINTER_REG) or
         result:=(current_procinfo.framepointer=NR_STACK_POINTER_REG) or

+ 12 - 0
compiler/x86_64/cpupara.pas

@@ -1036,6 +1036,18 @@ unit cpupara;
                       end;
                       end;
                       inc(mmretregidx);
                       inc(mmretregidx);
                     end;
                     end;
+                  X86_64_X87_CLASS:
+                    begin
+                      { must be followed by X86_64_X87UP_CLASS and that must be
+                        the last class }
+                      if (i<>(numclasses-2)) or
+                         (classes[i+1].typ<>X86_64_X87UP_CLASS) then
+                        internalerror(2014110401);
+                      paraloc^.loc:=LOC_FPUREGISTER;
+                      paraloc^.register:=NR_FPU_RESULT_REG;
+                      paraloc^.size:=OS_F80;
+                      break;
+                    end;
                   X86_64_NO_CLASS:
                   X86_64_NO_CLASS:
                     begin
                     begin
                       { empty record/array }
                       { empty record/array }