浏览代码

m68k: rewrote fixref and a_load_ref_ref, fixing a bunch of problems on ColdFire, unifying and simplifying the code a lot, and hopefully not killing anything in the process

git-svn-id: trunk@33446 -
Károly Balogh 9 年之前
父节点
当前提交
4e964c2ed7

+ 147 - 269
compiler/m68k/cgcpu.pas

@@ -93,7 +93,7 @@ unit cgcpu;
         procedure sign_extend(list: TAsmList;_oldsize : tcgsize; _newsize : tcgsize; reg: tregister);
         procedure sign_extend(list: TAsmList;_oldsize : tcgsize; _newsize : tcgsize; reg: tregister);
 
 
         procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
         procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
-        function fixref(list: TAsmList; var ref: treference): boolean;
+        function fixref(list: TAsmList; var ref: treference; fullyresolve: boolean): boolean;
         function force_to_dataregister(list: TAsmList; size: TCGSize; reg: TRegister): TRegister;
         function force_to_dataregister(list: TAsmList; size: TCGSize; reg: TRegister): TRegister;
         procedure move_if_needed(list: TAsmList; size: TCGSize; src: TRegister; dest: TRegister);
         procedure move_if_needed(list: TAsmList; size: TCGSize; src: TRegister; dest: TRegister);
      protected
      protected
@@ -350,7 +350,7 @@ unit cgcpu;
           { Push the data starting at ofs }
           { Push the data starting at ofs }
           href:=r;
           href:=r;
           inc(href.offset,ofs);
           inc(href.offset,ofs);
-          fixref(list,href);
+          fixref(list,href,false);
           if tcgsize2size[paraloc^.size]>cgpara.alignment then
           if tcgsize2size[paraloc^.size]>cgpara.alignment then
             pushsize:=paraloc^.size
             pushsize:=paraloc^.size
           else
           else
@@ -410,219 +410,134 @@ unit cgcpu;
             //list.concat(tai_comment.create(strpnew('a_loadaddr_ref_cgpara: PEA')));
             //list.concat(tai_comment.create(strpnew('a_loadaddr_ref_cgpara: PEA')));
             cgpara.check_simple_location;
             cgpara.check_simple_location;
             tmpref:=r;
             tmpref:=r;
-            fixref(list,tmpref);
+            fixref(list,tmpref,false);
             list.concat(taicpu.op_ref(A_PEA,S_NO,tmpref));
             list.concat(taicpu.op_ref(A_PEA,S_NO,tmpref));
           end
           end
         else
         else
           inherited a_loadaddr_ref_cgpara(list,r,cgpara);
           inherited a_loadaddr_ref_cgpara(list,r,cgpara);
       end;
       end;
 
 
-    function tcg68k.fixref(list: TAsmList; var ref: treference): boolean;
+
+    function tcg68k.fixref(list: TAsmList; var ref: treference; fullyresolve: boolean): boolean;
        var
        var
-         hreg,idxreg : tregister;
+         hreg : tregister;
          href : treference;
          href : treference;
          instr : taicpu;
          instr : taicpu;
-         scale : aint;
        begin
        begin
          result:=false;
          result:=false;
-         { The MC68020+ has extended
-           addressing capabilities with a 32-bit
-           displacement.
-         }
-         { first ensure that base is an address register }
-         if ((ref.base<>NR_NO) and (ref.index<>NR_NO)) and
-            (not isaddressregister(ref.base) and isaddressregister(ref.index)) and
-            (ref.scalefactor < 2) then
+         hreg:=NR_NO;
+
+         { NOTE: we don't have to fixup scaling in this function, because the memnode
+           won't generate scaling on CPUs which don't support it }
+
+         { first, deal with the symbol, if we have an index or base register.
+           in theory, the '020+ could deal with these, but it's better to avoid
+           long displacements on most members of the 68k family anyway }
+         if assigned(ref.symbol) and ((ref.base<>NR_NO) or (ref.index<>NR_NO)) then
            begin
            begin
-             { if we have both base and index registers, but base is data and index
-               is address, we can just swap them, as FPC always uses long index.
-               but we can only do this, if the index has no scalefactor }
-             hreg:=ref.base;
-             ref.base:=ref.index;
-             ref.index:=hreg;
-             //list.concat(tai_comment.create(strpnew('fixref: base and index swapped')));
+             //list.concat(tai_comment.create(strpnew('fixref: symbol with base or index')));
+
+             hreg:=getaddressregister(list);
+             reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
+             list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,hreg));
+             ref.offset:=0;
+             ref.symbol:=nil;
+
+             { if we have unused base or index, try to use it, otherwise fold the existing base,
+               also handle the case where the base might be a data register. }
+             if ref.base=NR_NO then
+               ref.base:=hreg
+             else
+               if (ref.index=NR_NO) and not isintregister(ref.base) then
+                 ref.index:=hreg
+               else
+                 begin
+                   list.concat(taicpu.op_reg_reg(A_ADD,S_L,ref.base,hreg));
+                   ref.base:=hreg;
+                 end;
+
+             { at this point we have base + (optional) index * scale }
            end;
            end;
 
 
-         if (not assigned (ref.symbol) and (current_settings.cputype<>cpu_MC68000)) and
-            (ref.base<>NR_NO) and not isaddressregister(ref.base) then
+         { deal with the case if our base is a dataregister }
+         if (ref.base<>NR_NO) and not isaddressregister(ref.base) then
            begin
            begin
+
              hreg:=getaddressregister(list);
              hreg:=getaddressregister(list);
-             instr:=taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg);
-             add_move_instruction(instr);
-             list.concat(instr);
-             fixref:=true;
-             ref.base:=hreg;
-           end;
-         if (current_settings.cputype=cpu_MC68020) then
-           exit;
-         { ToDo: check which constraints of Coldfire also apply to MC68000 }
-         case current_settings.cputype of
-           cpu_MC68000:
-             begin
-               if (ref.base<>NR_NO) then
-                 begin
-                   if (ref.index<>NR_NO) and assigned(ref.symbol) then
-                     begin
-                       hreg:=getaddressregister(list);
-                       list.concat(taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg));
-                       list.concat(taicpu.op_reg_reg(A_ADD,S_L,ref.index,hreg));
-                       ref.index:=NR_NO;
-                       ref.base:=hreg;
-                     end;
-                   { base + reg }
-                   if ref.index <> NR_NO then
-                      begin
-                         { base + reg + offset }
-                         if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
-                           begin
-                             hreg:=getaddressregister(list);
-                             list.concat(taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg));
-                             list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,hreg));
-                             fixref:=true;
-                             ref.offset:=0;
-                             ref.base:=hreg;
-                             exit;
-                           end;
-                      end
-                   else
-                   { base + offset }
-                   if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
-                     begin
-                       hreg:=getaddressregister(list);
-                       list.concat(taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg));
-                       list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,hreg));
-                       fixref:=true;
-                       ref.offset:=0;
-                       ref.base:=hreg;
-                       exit;
-                     end;
-                   if assigned(ref.symbol) then
-                     begin
-                       hreg:=getaddressregister(list);
-                       idxreg:=ref.base;
-                       ref.base:=NR_NO;
-                       list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,hreg));
-                       reference_reset_base(ref,hreg,0,ref.alignment);
-                       fixref:=true;
-                       ref.index:=idxreg;
-                     end
-                   else if not isaddressregister(ref.base) then
-                     begin
-                       hreg:=getaddressregister(list);
-                       instr:=taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg);
-                       //add_move_instruction(instr);
-                       list.concat(instr);
-                       fixref:=true;
-                       ref.base:=hreg;
-                     end;
-                 end
-               else
-                 { Note: symbol -> ref would be supported as long as ref does not
-                         contain a offset or index... (maybe something for the
-                         optimizer) }
-                 if Assigned(ref.symbol) and (ref.index<>NR_NO) then
+             if isaddressregister(ref.index) and (ref.scalefactor < 2) then
+               begin
+                 //list.concat(tai_comment.create(strpnew('fixref: base is dX, resolving with reverse regs')));
+
+                 reference_reset_base(href,ref.index,0,ref.alignment);
+                 href.index:=ref.base;
+                 { we can fold in an 8 bit offset "for free" }
+                 if isvalue8bit(ref.offset) then
                    begin
                    begin
-                     hreg:=cg.getaddressregister(list);
-                     idxreg:=ref.index;
-                     ref.index:=NR_NO;
-                     list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,hreg));
-                     reference_reset_base(ref,hreg,0,ref.alignment);
-                     ref.index:=idxreg;
-                     fixref:=true;
+                     href.offset:=ref.offset;
+                     ref.offset:=0;
                    end;
                    end;
-             end;
-           cpu_isa_a,
-           cpu_isa_a_p,
-           cpu_isa_b,
-           cpu_isa_c:
-             begin
-               if (ref.base<>NR_NO) then
-                 begin
-                   if assigned(ref.symbol) then
-                     begin
-                       //list.concat(tai_comment.create(strpnew('fixref: symbol')));
-                       hreg:=cg.getaddressregister(list);
-                       reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
-                       list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,hreg));
-                       if ref.index<>NR_NO then
-                         begin
-                           { fold the symbol + offset into the base, not the base into the index,
-                             because that might screw up the scalefactor of the reference }
-                           //list.concat(tai_comment.create(strpnew('fixref: symbol + offset (index + base)')));
-                           idxreg:=getaddressregister(list);
-                           reference_reset_base(href,ref.base,0,ref.alignment);
-                           href.index:=hreg;
-                           hreg:=getaddressregister(list);
-                           list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,hreg));
-                           ref.base:=hreg;
-                         end
-                       else
-                         ref.index:=hreg;
-
-                       ref.offset:=0;
-                       ref.symbol:=nil;
-                       fixref:=true;
-                     end
-                   else
-                     { base + reg }
-                     if ref.index <> NR_NO then
-                       begin
-                         { base + reg + offset }
-                         if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
-                           begin
-                             hreg:=getaddressregister(list);
-                             if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
-                               begin
-                                 instr:=taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg);
-                                 //add_move_instruction(instr);
-                                 list.concat(instr);
-                                 list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,hreg));
-                               end
-                             else
-                               begin
-                                 //list.concat(tai_comment.create(strpnew('fixref: base + reg + offset lea')));
-                                 reference_reset_base(href,ref.base,ref.offset,ref.alignment);
-                                 list.concat(taicpu.op_ref_reg(A_LEA,S_NO,href,hreg));
-                               end;
-                             fixref:=true;
-                             ref.base:=hreg;
-                             ref.offset:=0;
-                             exit;
-                           end;
-                       end
-                     else
-                       { base + offset }
-                       if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
-                         begin
-                           hreg:=getaddressregister(list);
-                           instr:=taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg);
-                           //add_move_instruction(instr);
-                           list.concat(instr);
-                           list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,hreg));
-                           fixref:=true;
-                           ref.offset:=0;
-                           ref.base:=hreg;
-                           exit;
-                         end;
-                 end
-               else
-                 { Note: symbol -> ref would be supported as long as ref does not
-                         contain a offset or index... (maybe something for the
-                         optimizer) }
-                 if Assigned(ref.symbol) {and (ref.index<>NR_NO)} then
+                 list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,hreg));
+                 ref.base:=hreg;
+                 ref.index:=NR_NO;
+                 result:=true;
+               end
+             else
+               begin
+                 //list.concat(tai_comment.create(strpnew('fixref: base is dX, can''t resolve with reverse regs')));
+
+                 instr:=taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg);
+                 add_move_instruction(instr);
+                 list.concat(instr);
+                 ref.base:=hreg;
+                 result:=true;
+               end;
+           end;
+
+         { deal with large offsets on non-020+ }
+         if current_settings.cputype<>cpu_MC68020 then
+           begin
+             if ((ref.index<>NR_NO) and not isvalue8bit(ref.offset)) or
+                ((ref.base<>NR_NO) and not isvalue16bit(ref.offset)) then
+               begin
+                 //list.concat(tai_comment.create(strpnew('fixref: handling large offsets')));
+                 { if we have a temp register from above, we can just add to it }
+                 if hreg=NR_NO then
+                   hreg:=getaddressregister(list);
+
+                 if isvalue16bit(ref.offset) then
                    begin
                    begin
-                     hreg:=cg.getaddressregister(list);
-                     idxreg:=ref.index;
-                     scale:=ref.scalefactor;
-                     ref.index:=NR_NO;
-                     list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,hreg));
-                     reference_reset_base(ref,hreg,0,ref.alignment);
-                     ref.index:=idxreg;
-                     ref.scalefactor:=scale;
-                     fixref:=true;
+                     reference_reset_base(href,ref.base,ref.offset,ref.alignment);
+                     list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,hreg));
+                   end
+                 else
+                   begin
+                     instr:=taicpu.op_reg_reg(A_MOVE,S_L,ref.base,hreg);
+                     add_move_instruction(instr);
+                     list.concat(instr);
+                     list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,hreg));
                    end;
                    end;
-             end;
-         end;
+                 ref.offset:=0;
+                 ref.base:=hreg;
+                 result:=true;
+               end;
+           end;
+
+         { fully resolve the reference to an address register, if we're told to do so
+           and there's a reason to do so }
+         if fullyresolve and
+            ((ref.index<>NR_NO) or assigned(ref.symbol) or (ref.offset<>0)) then
+           begin
+             //list.concat(tai_comment.create(strpnew('fixref: fully resolve to register')));
+             if hreg=NR_NO then
+               hreg:=getaddressregister(list);
+             list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,hreg));
+             ref.base:=hreg;
+             ref.index:=NR_NO;
+             ref.scalefactor:=1;
+             ref.symbol:=nil;
+             ref.offset:=0;
+             result:=true;
+           end;
        end;
        end;
 
 
 
 
@@ -805,7 +720,7 @@ unit cgcpu;
       begin
       begin
         a:=longint(a);
         a:=longint(a);
         href:=ref;
         href:=ref;
-        fixref(list,href);
+        fixref(list,href,false);
         if (a=0) and not (current_settings.cputype = cpu_mc68000) then
         if (a=0) and not (current_settings.cputype = cpu_mc68000) then
           list.concat(taicpu.op_ref(A_CLR,tcgsize2opsize[tosize],href))
           list.concat(taicpu.op_ref(A_CLR,tcgsize2opsize[tosize],href))
         else if (tcgsize2opsize[tosize]=S_L) and
         else if (tcgsize2opsize[tosize]=S_L) and
@@ -845,13 +760,18 @@ 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;
+        hreg : tregister;
       begin
       begin
         href := ref;
         href := ref;
-        fixref(list,href);
+        hreg := register;
+        fixref(list,href,false);
         if tcgsize2size[fromsize]<tcgsize2size[tosize] then
         if tcgsize2size[fromsize]<tcgsize2size[tosize] then
-          a_load_reg_reg(list,fromsize,tosize,register,register);
+          begin
+            hreg:=getintregister(list,tosize);
+            a_load_reg_reg(list,fromsize,tosize,register,hreg);
+          end;
         { move to destination reference }
         { move to destination reference }
-        list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],register,href));
+        list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],hreg,href));
       end;
       end;
 
 
 
 
@@ -859,77 +779,31 @@ unit cgcpu;
       var
       var
         aref: treference;
         aref: treference;
         bref: treference;
         bref: treference;
-        tmpref : treference;
-        dofix : boolean;
+        usetemp: boolean;
         hreg: TRegister;
         hreg: TRegister;
       begin
       begin
+        usetemp:=TCGSize2OpSize[fromsize]<>TCGSize2OpSize[tosize];
+
         aref := sref;
         aref := sref;
         bref := dref;
         bref := dref;
-        fixref(list,aref);
-        fixref(list,bref);
-        if TCGSize2OpSize[fromsize]<>TCGSize2OpSize[tosize] then
+        fixref(list,aref,false);
+
+        if usetemp then
           begin
           begin
-            { if we need to change the size then always use a temporary
-              register }
+            { if we will use a temp register, we don't need to fully resolve 
+              the dest ref, not even on coldfire }
+            fixref(list,bref,false); 
+            { if we need to change the size then always use a temporary register }
             hreg:=getintregister(list,fromsize);
             hreg:=getintregister(list,fromsize);
             list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
             list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
             sign_extend(list,fromsize,tosize,hreg);
             sign_extend(list,fromsize,tosize,hreg);
             list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],hreg,bref));
             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
+          end
+        else
           begin
           begin
-            { TODO : move.b/w only allowed in newer coldfires... (ISA_B+) }
-
-            dofix:=false;
-            if { (d16,Ax) and (d8,Ax,Xi) }
-                (
-                  (aref.base<>NR_NO) and
-                  (
-                    (aref.index<>NR_NO) or
-                    (aref.offset<>0)
-                  )
-                ) or
-                { (xxx) }
-                assigned(aref.symbol) then
-              begin
-                if aref.index<>NR_NO then
-                  begin
-                    dofix:={ (d16,Ax) and (d8,Ax,Xi) }
-                           (
-                             (bref.base<>NR_NO) and
-                             (
-                               (bref.index<>NR_NO) or
-                               (bref.offset<>0)
-                             )
-                           ) or
-                           { (xxx) }
-                           assigned(bref.symbol);
-                  end
-                else
-                  { offset <> 0, but no index }
-                  begin
-                    dofix:={ (d8,Ax,Xi) }
-                           (
-                             (bref.base<>NR_NO) and
-                             (bref.index<>NR_NO)
-                           ) or
-                           { (xxx) }
-                           assigned(bref.symbol);
-                  end;
-              end;
-
-            if dofix then
-              begin
-                hreg:=getaddressregister(list);
-                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;
+            fixref(list,bref,current_settings.cputype in cpu_coldfire);
+            list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],aref,bref));
           end;
           end;
-        list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],aref,bref));
       end;
       end;
 
 
 
 
@@ -971,7 +845,7 @@ unit cgcpu;
        opsize: topsize;
        opsize: topsize;
       begin
       begin
          href:=ref;
          href:=ref;
-         fixref(list,href);
+         fixref(list,href,false);
          if tcgsize2size[fromsize]<tcgsize2size[tosize] then
          if tcgsize2size[fromsize]<tcgsize2size[tosize] then
            size:=fromsize
            size:=fromsize
          else
          else
@@ -999,7 +873,7 @@ unit cgcpu;
         hreg : tregister;
         hreg : tregister;
       begin
       begin
         href:=ref;
         href:=ref;
-        fixref(list, href);
+        fixref(list, href, false);
         if not isaddressregister(r) then
         if not isaddressregister(r) then
           begin
           begin
             hreg:=getaddressregister(list);
             hreg:=getaddressregister(list);
@@ -1031,7 +905,7 @@ unit cgcpu;
         if opsize = S_FX then
         if opsize = S_FX then
           internalerror(20020729);
           internalerror(20020729);
         href := ref;
         href := ref;
-        fixref(list,href);
+        fixref(list,href,false);
         list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
         list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
       end;
       end;
 
 
@@ -1045,7 +919,7 @@ unit cgcpu;
         if opsize = S_FX then
         if opsize = S_FX then
           internalerror(20020729);
           internalerror(20020729);
         href := ref;
         href := ref;
-        fixref(list,href);
+        fixref(list,href,false);
         list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg,href));
         list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg,href));
       end;
       end;
 
 
@@ -1092,7 +966,7 @@ unit cgcpu;
           if use_push(cgpara) and (current_settings.fputype in [fpu_68881]) then
           if use_push(cgpara) and (current_settings.fputype in [fpu_68881]) then
             begin
             begin
               fref:=ref;
               fref:=ref;
-              fixref(list,fref);
+              fixref(list,fref,false);
               { fmove can't do <ea> -> <ea>, so move it to an fpreg first }
               { fmove can't do <ea> -> <ea>, so move it to an fpreg first }
               freg:=getfpuregister(list,size);
               freg:=getfpuregister(list,size);
               a_loadfpu_ref_reg(list,size,size,fref,freg);
               a_loadfpu_ref_reg(list,size,size,fref,freg);
@@ -1284,10 +1158,10 @@ unit cgcpu;
           OP_SUB :
           OP_SUB :
             begin
             begin
               href:=ref;
               href:=ref;
-              fixref(list,href);
               { add/sub works the same way, so have it unified here }
               { add/sub works the same way, so have it unified here }
               if (a >= 1) and (a <= 8) then
               if (a >= 1) and (a <= 8) then
                 begin
                 begin
+                  fixref(list,href,false);
                   if (op = OP_ADD) then
                   if (op = OP_ADD) then
                     opcode:=A_ADDQ
                     opcode:=A_ADDQ
                   else
                   else
@@ -1296,7 +1170,10 @@ unit cgcpu;
                 end
                 end
               else
               else
                 if not(current_settings.cputype in cpu_coldfire) then
                 if not(current_settings.cputype in cpu_coldfire) then
-                  list.concat(taicpu.op_const_ref(opcode, opsize, a, href))
+                  begin
+                    fixref(list,href,false);
+                    list.concat(taicpu.op_const_ref(opcode, opsize, a, href));
+                  end
                 else
                 else
                   { on ColdFire, ADDI/SUBI cannot act on memory
                   { on ColdFire, ADDI/SUBI cannot act on memory
                     so we can only go through a register }
                     so we can only go through a register }
@@ -1437,7 +1314,7 @@ unit cgcpu;
           OP_SUB :
           OP_SUB :
             begin
             begin
               href:=ref;
               href:=ref;
-              fixref(list,href);
+              fixref(list,href,false);
               { areg -> ref arithmetic operations are impossible on 68k }
               { areg -> ref arithmetic operations are impossible on 68k }
               hreg:=force_to_dataregister(list,size,reg);
               hreg:=force_to_dataregister(list,size,reg);
               { add/sub works the same way, so have it unified here }
               { add/sub works the same way, so have it unified here }
@@ -1518,7 +1395,7 @@ unit cgcpu;
           begin
           begin
             //list.concat(tai_comment.create(strpnew('a_cmp_const_ref_label with TST')));
             //list.concat(tai_comment.create(strpnew('a_cmp_const_ref_label with TST')));
             tmpref:=ref;
             tmpref:=ref;
-            fixref(list,tmpref);
+            fixref(list,tmpref,false);
             list.concat(taicpu.op_ref(A_TST,tcgsize2opsize[size],tmpref));
             list.concat(taicpu.op_ref(A_TST,tcgsize2opsize[size],tmpref));
             a_jmp_cond(list,cmp_op,l);
             a_jmp_cond(list,cmp_op,l);
           end
           end
@@ -1738,6 +1615,7 @@ unit cgcpu;
         if not nostackframe then
         if not nostackframe then
           begin
           begin
             { size can't be negative }
             { size can't be negative }
+            localsize:=align(localsize,4);
             if (localsize < 0) then
             if (localsize < 0) then
               internalerror(2006122601);
               internalerror(2006122601);
 
 
@@ -2273,7 +2151,7 @@ unit cgcpu;
           OP_AND,OP_OR:
           OP_AND,OP_OR:
             begin
             begin
               tempref:=ref;
               tempref:=ref;
-              tcg68k(cg).fixref(list,tempref);
+              tcg68k(cg).fixref(list,tempref,false);
               inc(tempref.offset,4);
               inc(tempref.offset,4);
               list.concat(taicpu.op_ref_reg(topcg2tasmop[op],S_L,tempref,reg.reglo));
               list.concat(taicpu.op_ref_reg(topcg2tasmop[op],S_L,tempref,reg.reglo));
               dec(tempref.offset,4);
               dec(tempref.offset,4);

+ 3 - 2
compiler/m68k/cpuinfo.pas

@@ -120,12 +120,13 @@ Const
                                  genericlevel3optimizerswitches-
                                  genericlevel3optimizerswitches-
                                  { no need to write info about those }
                                  { no need to write info about those }
                                  [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
                                  [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
-                                 [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,
+                                 [cs_opt_regvar,cs_opt_stackframe,cs_opt_loopunroll,
+                                  cs_opt_tailrecursion,cs_opt_nodecse,
                                   cs_opt_reorder_fields,cs_opt_fastmath];
                                   cs_opt_reorder_fields,cs_opt_fastmath];
 
 
    level1optimizerswitches = genericlevel1optimizerswitches;
    level1optimizerswitches = genericlevel1optimizerswitches;
    level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
    level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
-     [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse];
+     [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
    level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
    level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [];
 
 

+ 2 - 2
compiler/m68k/hlcgcpu.pas

@@ -88,7 +88,7 @@ implementation
     begin
     begin
       //list.concat(tai_comment.create(strpnew('a_bit_set_reg_ref: called!')));
       //list.concat(tai_comment.create(strpnew('a_bit_set_reg_ref: called!')));
       sref:=get_bit_reg_ref_sref(list,fromsize,tosize,bitnumber,ref);
       sref:=get_bit_reg_ref_sref(list,fromsize,tosize,bitnumber,ref);
-      tcg68k(cg).fixref(list,sref.ref);
+      tcg68k(cg).fixref(list,sref.ref,false);
 
 
       tmpvalue:=getintregister(list,ptruinttype);
       tmpvalue:=getintregister(list,ptruinttype);
       a_load_const_reg(list,ptruinttype,7,tmpvalue);
       a_load_const_reg(list,ptruinttype,7,tmpvalue);
@@ -105,7 +105,7 @@ implementation
     begin
     begin
       //list.concat(tai_comment.create(strpnew('a_bit_set_const_ref: called!')));
       //list.concat(tai_comment.create(strpnew('a_bit_set_const_ref: called!')));
       sref:=get_bit_const_ref_sref(bitnumber,destsize,ref);
       sref:=get_bit_const_ref_sref(bitnumber,destsize,ref);
-      tcg68k(cg).fixref(list,sref.ref);
+      tcg68k(cg).fixref(list,sref.ref,current_settings.cputype in cpu_coldfire);
 
 
       { memory accesses of bset/bclr are always byte, so no alignment problem }
       { memory accesses of bset/bclr are always byte, so no alignment problem }
       list.concat(taicpu.op_const_ref(bit_set_clr_instr[doset],S_NO,8-sref.startbit-1,sref.ref));
       list.concat(taicpu.op_const_ref(bit_set_clr_instr[doset],S_NO,8-sref.startbit-1,sref.ref));

+ 6 - 6
compiler/m68k/n68kadd.pas

@@ -157,7 +157,7 @@ implementation
                 LOC_REFERENCE,LOC_CREFERENCE:
                 LOC_REFERENCE,LOC_CREFERENCE:
                     begin
                     begin
                       href:=right.location.reference;
                       href:=right.location.reference;
-                      tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+                      tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
                       current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,tcgsize2opsize[right.location.size],href,location.register));
                       current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,tcgsize2opsize[right.location.size],href,location.register));
                     end
                     end
                 else
                 else
@@ -194,7 +194,7 @@ implementation
                 LOC_REFERENCE,LOC_CREFERENCE:
                 LOC_REFERENCE,LOC_CREFERENCE:
                     begin
                     begin
                       href:=right.location.reference;
                       href:=right.location.reference;
-                      tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+                      tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
                       current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FCMP,tcgsize2opsize[right.location.size],href,left.location.register));
                       current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FCMP,tcgsize2opsize[right.location.size],href,left.location.register));
                     end
                     end
                 else
                 else
@@ -307,7 +307,7 @@ implementation
              LOC_CREFERENCE:
              LOC_CREFERENCE:
                begin
                begin
                  href:=left.location.reference;
                  href:=left.location.reference;
-                 tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+                 tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
                  current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,opsize,href));
                  current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,opsize,href));
                  location_freetemp(current_asmdata.CurrAsmList,left.location);
                  location_freetemp(current_asmdata.CurrAsmList,left.location);
                end;
                end;
@@ -350,7 +350,7 @@ implementation
          LOC_CREFERENCE:
          LOC_CREFERENCE:
            begin
            begin
              href:=right.location.reference;
              href:=right.location.reference;
-             tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+             tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_CMP,opsize,href,
              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_CMP,opsize,href,
                left.location.register));
                left.location.register));
            end;
            end;
@@ -475,7 +475,7 @@ implementation
               LOC_CREFERENCE:
               LOC_CREFERENCE:
                 begin
                 begin
                   href:=left.location.reference;
                   href:=left.location.reference;
-                  tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+                  tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
                   current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,S_L,href));
                   current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,S_L,href));
                   firstjmp64bitcmp;
                   firstjmp64bitcmp;
                   inc(href.offset,4);
                   inc(href.offset,4);
@@ -518,7 +518,7 @@ implementation
           LOC_REFERENCE,LOC_CREFERENCE:
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
               href:=right.location.reference;
               href:=right.location.reference;
-              tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+              tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
               current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_CMP,S_L,href,left.location.register64.reghi));
               current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_CMP,S_L,href,left.location.register64.reghi));
               firstjmp64bitcmp;
               firstjmp64bitcmp;
               inc(href.offset,4);
               inc(href.offset,4);

+ 1 - 1
compiler/m68k/n68kcnv.pas

@@ -148,7 +148,7 @@ implementation
           LOC_REFERENCE,LOC_CREFERENCE:
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
               ref:=left.location.reference;
               ref:=left.location.reference;
-              tcg68k(cg).fixref(current_asmdata.CurrAsmList,ref);
+              tcg68k(cg).fixref(current_asmdata.CurrAsmList,ref,false);
               current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FMOVE,TCGSize2OpSize[opsize],ref,location.register));
               current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FMOVE,TCGSize2OpSize[opsize],ref,location.register));
             end
             end
           else
           else

+ 1 - 1
compiler/m68k/n68kinl.pas

@@ -216,7 +216,7 @@ implementation
                   begin
                   begin
                     location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
                     location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
                     href:=left.location.reference;
                     href:=left.location.reference;
-                    tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+                    tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
                     current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,tcgsize2opsize[left.location.size],href,location.register));
                     current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,tcgsize2opsize[left.location.size],href,location.register));
                   end;
                   end;
                 else
                 else

+ 2 - 2
compiler/m68k/n68kmat.pas

@@ -89,7 +89,7 @@ implementation
               LOC_REFERENCE,
               LOC_REFERENCE,
               LOC_CREFERENCE:
               LOC_CREFERENCE:
                 begin
                 begin
-                  tcg68k(cg).fixref(current_asmdata.CurrAsmList,left.location.reference);
+                  tcg68k(cg).fixref(current_asmdata.CurrAsmList,left.location.reference,false);
                   if is_64bit(resultdef) then
                   if is_64bit(resultdef) then
                    begin
                    begin
                      hreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_32);
                      hreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_32);
@@ -194,7 +194,7 @@ implementation
             begin
             begin
               location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
               location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
               href:=left.location.reference;
               href:=left.location.reference;
-              tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+              tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,false);
               current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FNEG,tcgsize2opsize[left.location.size],href,location.register));
               current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FNEG,tcgsize2opsize[left.location.size],href,location.register));
             end;
             end;
           LOC_FPUREGISTER:
           LOC_FPUREGISTER: