Browse Source

Correctly handle loads of different sizes. Fixes 1 test. Might be more, but some other bugs might hide it.

m68k/cgcpu.pas, tcg68k:
  * a_load_ref_cgpara: use pashsize instead of paraloc^.size as the latter could be OS_NO and thus a "move" instead of a "move.x" will be generated resulting in a word move when a long or byte move might have been necessary
  * a_load_reg_ref: use the smallest size when moving the value to a reference
  * a_load_ref_ref: when the size is different always use a temporary register for a ref to ref move
  * a_load_ref_ref: when doing a fixed move for Coldfire use the correct ref (that's another embarrasing error...) and size (fixes usage of String[Index] for a const array parameter)
  * a_load_ref_reg: use the smallest size when moving the value from a reference
  * g_concatcopy: don't use source.alignment as that doesn't contain the correct value and also load the value into the temp register using the correct size (fixes passing of small values as parameters, like chars)

git-svn-id: trunk@25624 -
svenbarth 12 years ago
parent
commit
0cb2bda0a5
2 changed files with 39 additions and 12 deletions
  1. 33 11
      compiler/m68k/cgcpu.pas
  2. 6 1
      compiler/m68k/cpupara.pas

+ 33 - 11
compiler/m68k/cgcpu.pas

@@ -327,7 +327,7 @@ unit cgcpu;
           else
           else
             pushsize:=int_cgsize(cgpara.alignment);
             pushsize:=int_cgsize(cgpara.alignment);
 
 
-          reference_reset_base(ref, NR_STACK_POINTER_REG, 0, tcgsize2size[paraloc^.size]);
+          reference_reset_base(ref, NR_STACK_POINTER_REG, 0, tcgsize2size[pushsize]);
           ref.direction := dir_dec;
           ref.direction := dir_dec;
 
 
           if tcgsize2size[paraloc^.size]<cgpara.alignment then
           if tcgsize2size[paraloc^.size]<cgpara.alignment then
@@ -774,14 +774,19 @@ unit cgcpu;
     procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
     procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
       var
       var
        href : treference;
        href : treference;
+        size : tcgsize;
       begin
       begin
         href := ref;
         href := ref;
         fixref(list,href);
         fixref(list,href);
 {$ifdef DEBUG_CHARLIE}
 {$ifdef DEBUG_CHARLIE}
         list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
         list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
 {$endif DEBUG_CHARLIE}
 {$endif DEBUG_CHARLIE}
+        if tcgsize2size[fromsize]<tcgsize2size[tosize] then
+          size:=fromsize
+        else
+          size:=tosize;
         { move to destination reference }
         { move to destination reference }
-        list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[fromsize],register,href));
+        list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[size],register,href));
       end;
       end;
 
 
 
 
@@ -789,6 +794,7 @@ unit cgcpu;
       var
       var
         aref: treference;
         aref: treference;
         bref: treference;
         bref: treference;
+        tmpref : treference;
         dofix : boolean;
         dofix : boolean;
         hreg: TRegister;
         hreg: TRegister;
       begin
       begin
@@ -799,6 +805,16 @@ unit cgcpu;
 {$ifdef DEBUG_CHARLIE}
 {$ifdef DEBUG_CHARLIE}
 //        writeln('a_load_ref_ref');
 //        writeln('a_load_ref_ref');
 {$endif DEBUG_CHARLIE}
 {$endif DEBUG_CHARLIE}
+        if fromsize<>tosize then
+          begin
+            { if we need to change the size then always use a temporary
+              register }
+            hreg:=getintregister(list,fromsize);
+            list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
+            sign_extend(list,fromsize,hreg);
+            list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],hreg,bref));
+            exit;
+          end;
         { Coldfire dislikes certain move combinations }
         { Coldfire dislikes certain move combinations }
         if current_settings.cputype in cpu_coldfire then
         if current_settings.cputype in cpu_coldfire then
           begin
           begin
@@ -845,8 +861,9 @@ unit cgcpu;
             if dofix then
             if dofix then
               begin
               begin
                 hreg:=getaddressregister(list);
                 hreg:=getaddressregister(list);
-                list.concat(taicpu.op_ref_reg(A_LEA,S_L,bref,hreg));
-                list.concat(taicpu.op_reg_ref(A_MOVE,S_L{TCGSize2OpSize[fromsize]},hreg,bref));
+                reference_reset_base(tmpref,hreg,0,0);
+                list.concat(taicpu.op_ref_reg(A_LEA,S_L,aref,hreg));
+                list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],tmpref,bref));
                 exit;
                 exit;
               end;
               end;
           end;
           end;
@@ -871,10 +888,15 @@ unit cgcpu;
     procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
     procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
       var
       var
        href : treference;
        href : treference;
+       size : tcgsize;
       begin
       begin
          href:=ref;
          href:=ref;
          fixref(list,href);
          fixref(list,href);
-         list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
+         if tcgsize2size[fromsize]<tcgsize2size[tosize] then
+           size:=fromsize
+         else
+           size:=tosize;
+         list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[size],href,register));
          { extend the value in the register }
          { extend the value in the register }
          sign_extend(list, fromsize, register);
          sign_extend(list, fromsize, register);
       end;
       end;
@@ -1554,14 +1576,14 @@ unit cgcpu;
               { move a word }
               { move a word }
               if len>1 then
               if len>1 then
                 begin
                 begin
-                   if (orglen<source.alignment) and
+                   if (orglen<sizeof(aint)) and
                        (source.base=NR_FRAME_POINTER_REG) and
                        (source.base=NR_FRAME_POINTER_REG) and
                        (source.offset>0) then
                        (source.offset>0) then
                      { copy of param to local location }
                      { copy of param to local location }
-                     alignsize:=int_cgsize(source.alignment)
+                     alignsize:=OS_INT
                    else
                    else
                      alignsize:=OS_16;
                      alignsize:=OS_16;
-                   a_load_ref_reg(list,alignsize,OS_16,srcref,hregister);
+                   a_load_ref_reg(list,alignsize,alignsize,srcref,hregister);
                    a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
                    a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
                    inc(srcref.offset,2);
                    inc(srcref.offset,2);
                    inc(dstref.offset,2);
                    inc(dstref.offset,2);
@@ -1570,14 +1592,14 @@ unit cgcpu;
               { move a single byte }
               { move a single byte }
               if len>0 then
               if len>0 then
                 begin
                 begin
-                   if (orglen<source.alignment) and
+                   if (orglen<sizeof(aint)) and
                        (source.base=NR_FRAME_POINTER_REG) and
                        (source.base=NR_FRAME_POINTER_REG) and
                        (source.offset>0) then
                        (source.offset>0) then
                      { copy of param to local location }
                      { copy of param to local location }
-                     alignsize:=int_cgsize(source.alignment)
+                     alignsize:=OS_INT
                    else
                    else
                      alignsize:=OS_8;
                      alignsize:=OS_8;
-                   a_load_ref_reg(list,alignsize,OS_8,srcref,hregister);
+                   a_load_ref_reg(list,alignsize,alignsize,srcref,hregister);
                    a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
                    a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
                 end
                 end
            end
            end

+ 6 - 1
compiler/m68k/cpupara.pas

@@ -395,8 +395,13 @@ unit cpupara;
 		    writeln('loc reference');
 		    writeln('loc reference');
 {$endif DEBUG_CHARLIE}
 {$endif DEBUG_CHARLIE}
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.loc:=LOC_REFERENCE;
-                    paraloc^.size:=int_cgsize(paralen);
                     paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc);
                     paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc);
+                    if paradef.typ<>orddef then
+                      paracgsize:=int_cgsize(paralen);
+                    if paracgsize=OS_NO then
+                      paraloc^.size:=OS_INT
+                    else
+                      paraloc^.size:=paracgsize;
                     if (side = callerside) then
                     if (side = callerside) then
                       paraloc^.reference.index:=NR_STACK_POINTER_REG
                       paraloc^.reference.index:=NR_STACK_POINTER_REG
                     else
                     else