Browse Source

* fix methodpointers in registers on big endian targets

git-svn-id: trunk@22362 -
florian 13 years ago
parent
commit
67744ef46e
5 changed files with 43 additions and 5 deletions
  1. 12 0
      compiler/cgbase.pas
  2. 8 2
      compiler/cgobj.pas
  3. 6 2
      compiler/hlcgobj.pas
  4. 8 1
      compiler/ncgcal.pas
  5. 9 0
      compiler/ncgld.pas

+ 12 - 0
compiler/cgbase.pas

@@ -283,6 +283,18 @@ interface
        tvarregable2tcgloc : array[tvarregable] of tcgloc = (LOC_VOID,
           LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER,LOC_CREGISTER);
 
+{$ifdef cpu64bitalu}
+       { operand size describing an unsigned value in a pair of int registers }
+       OS_PAIR = OS_128;
+       { operand size describing an signed value in a pair of int registers }
+       OS_SPAIR = OS_S128;
+{$else cpu64bitalu}
+       { operand size describing an unsigned value in a pair of int registers }
+       OS_PAIR = OS_64;
+       { operand size describing an signed value in a pair of int registers }
+       OS_SPAIR = OS_S64;
+{$endif cpu64bitalu}
+
        { Table to convert tcgsize variables to the correspondending
          unsigned types }
        tcgsize2unsigned : array[tcgsize] of tcgsize = (OS_NO,

+ 8 - 2
compiler/cgobj.pas

@@ -468,6 +468,7 @@ unit cgobj;
         procedure a_load128_ref_reg(list : TAsmList;const ref : treference;reg : tregister128);virtual;
         procedure a_load128_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);virtual;
         procedure a_load128_reg_loc(list : TAsmList;reg : tregister128;const l : tlocation);virtual;
+        procedure a_load128_const_reg(list : TAsmList;valuelo,valuehi : int64;reg : tregister128);virtual;
 
         procedure a_load128_loc_cgpara(list : TAsmList;const l : tlocation;const paraloc : TCGPara);virtual;
         procedure a_load128_ref_cgpara(list: TAsmList; const r: treference;const paraloc: tcgpara);
@@ -2608,8 +2609,6 @@ implementation
       end;
 
 
-
-
     procedure tcg128.a_load128_reg_reg(list: TAsmList; regsrc,
       regdst: tregister128);
       begin
@@ -2707,6 +2706,13 @@ implementation
         end;
       end;
 
+    procedure tcg128.a_load128_const_reg(list: TAsmList; valuelo,
+     valuehi: int64; reg: tregister128);
+     begin
+       cg.a_load_const_reg(list,OS_32,aint(valuelo),reg.reglo);
+       cg.a_load_const_reg(list,OS_32,aint(valuehi),reg.reghi);
+     end;
+
 
     procedure tcg128.a_load128_loc_cgpara(list: TAsmList; const l: tlocation;
       const paraloc: TCGPara);

+ 6 - 2
compiler/hlcgobj.pas

@@ -3882,11 +3882,15 @@ implementation
          case tstaticvarsym(p).initialloc.loc of
            LOC_CREGISTER :
              begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+               if (tstaticvarsym(p).initialloc.size in [OS_128,OS_S128]) then
+                 cg128.a_load128_const_reg(TAsmList(arg),0,0,tstaticvarsym(p).initialloc.register128)
+               else
+{$else cpu64bitalu}
                if (tstaticvarsym(p).initialloc.size in [OS_64,OS_S64]) then
                  cg64.a_load64_const_reg(TAsmList(arg),0,tstaticvarsym(p).initialloc.register64)
                else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                  a_load_const_reg(TAsmList(arg),tstaticvarsym(p).vardef,0,
                      tstaticvarsym(p).initialloc.register);
              end;

+ 8 - 1
compiler/ncgcal.pas

@@ -890,7 +890,14 @@ implementation
               if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
                 cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
               else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-                hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,right.location.register,pvreg)
+                begin
+                  { in case left is a method pointer and we are on a big endian target, then
+                    the method address is stored in registerhi }
+                  if (target_info.endian=endian_big) and (right.location.size in [OS_PAIR,OS_SPAIR]) then
+                    hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,right.location.registerhi,pvreg)
+                  else
+                    hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,right.location.register,pvreg);
+                end
               else
                 hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,right.location,pvreg);
               location_freetemp(current_asmdata.CurrAsmList,right.location);

+ 9 - 0
compiler/ncgld.pas

@@ -531,6 +531,15 @@ implementation
                          location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
                          cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
                        end;
+
+                     { to get methodpointers stored correctly, code and self register must be swapped on
+                       big endian targets }
+                     if target_info.endian=endian_big then
+                       begin
+                         hregister:=location.register;
+                         location.register:=location.registerhi;
+                         location.registerhi:=hregister;
+                       end;
                    end
                  else
                    begin