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
             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;
 
           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);
       var
        href : treference;
+        size : tcgsize;
       begin
         href := ref;
         fixref(list,href);
 {$ifdef DEBUG_CHARLIE}
         list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
 {$endif DEBUG_CHARLIE}
+        if tcgsize2size[fromsize]<tcgsize2size[tosize] then
+          size:=fromsize
+        else
+          size:=tosize;
         { 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;
 
 
@@ -789,6 +794,7 @@ unit cgcpu;
       var
         aref: treference;
         bref: treference;
+        tmpref : treference;
         dofix : boolean;
         hreg: TRegister;
       begin
@@ -799,6 +805,16 @@ unit cgcpu;
 {$ifdef DEBUG_CHARLIE}
 //        writeln('a_load_ref_ref');
 {$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 }
         if current_settings.cputype in cpu_coldfire then
           begin
@@ -845,8 +861,9 @@ unit cgcpu;
             if dofix then
               begin
                 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;
               end;
           end;
@@ -871,10 +888,15 @@ unit cgcpu;
     procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
       var
        href : treference;
+       size : tcgsize;
       begin
          href:=ref;
          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 }
          sign_extend(list, fromsize, register);
       end;
@@ -1554,14 +1576,14 @@ unit cgcpu;
               { move a word }
               if len>1 then
                 begin
-                   if (orglen<source.alignment) and
+                   if (orglen<sizeof(aint)) and
                        (source.base=NR_FRAME_POINTER_REG) and
                        (source.offset>0) then
                      { copy of param to local location }
-                     alignsize:=int_cgsize(source.alignment)
+                     alignsize:=OS_INT
                    else
                      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);
                    inc(srcref.offset,2);
                    inc(dstref.offset,2);
@@ -1570,14 +1592,14 @@ unit cgcpu;
               { move a single byte }
               if len>0 then
                 begin
-                   if (orglen<source.alignment) and
+                   if (orglen<sizeof(aint)) and
                        (source.base=NR_FRAME_POINTER_REG) and
                        (source.offset>0) then
                      { copy of param to local location }
-                     alignsize:=int_cgsize(source.alignment)
+                     alignsize:=OS_INT
                    else
                      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);
                 end
            end

+ 6 - 1
compiler/m68k/cpupara.pas

@@ -395,8 +395,13 @@ unit cpupara;
 		    writeln('loc reference');
 {$endif DEBUG_CHARLIE}
                     paraloc^.loc:=LOC_REFERENCE;
-                    paraloc^.size:=int_cgsize(paralen);
                     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
                       paraloc^.reference.index:=NR_STACK_POINTER_REG
                     else