فهرست منبع

* m68k: partially improved code generation for comparisons.

git-svn-id: trunk@28283 -
sergei 11 سال پیش
والد
کامیت
2c8264c42b
1فایلهای تغییر یافته به همراه92 افزوده شده و 37 حذف شده
  1. 92 37
      compiler/m68k/n68kadd.pas

+ 92 - 37
compiler/m68k/n68kadd.pas

@@ -244,7 +244,6 @@ implementation
     procedure t68kaddnode.second_cmpordinal;
      var
       unsigned : boolean;
-      useconst : boolean;
       tmpreg : tregister;
       opsize : topsize;
       cmpsize : tcgsize;
@@ -255,7 +254,7 @@ implementation
                    not(is_signed(right.resultdef));
        { this puts constant operand (if any) to the right }
        pass_left_right;
-       { tentatively assume left size (correct for possible TST/CMPI, will fix later) }
+       { tentatively assume left size (correct for possible TST, will fix later) }
        cmpsize:=def_cgsize(left.resultdef);
        opsize:=tcgsize2opsize[cmpsize];
 
@@ -283,37 +282,26 @@ implementation
            exit;
          end;
 
-       { ToDo : set "allowconstants" to True, but this seems to upset Coldfire
-                a bit for the CMP instruction => check manual and implement
-                exception accordingly below }
-       { load values into registers (except constants) }
-       force_reg_left_right(true, false);
-
-       useconst := false;
-
-        if tcgsize2size[right.location.size]=tcgsize2size[left.location.size] then
-          cmpsize:=left.location.size
+       { Coldfire supports byte/word compares only starting with ISA_B,
+         !!see remark about Qemu weirdness in tcg68k.a_cmp_const_reg_label }
+       if (opsize<>S_L) and (current_settings.cputype in cpu_coldfire{-[cpu_isa_b,cpu_isa_c]}) then
+         begin
+           { 1) Extension is needed for LOC_REFERENCE, but what about LOC_REGISTER ? Perhaps after fixing cg we can assume
+                that high bits of registers are correct.
+             2) Assuming that extension depends only on source signedness --> destination OS_32 is acceptable. }
+           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,cgsize_orddef(OS_32),false);
+           if (right.location.loc<>LOC_CONSTANT) then
+             hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,cgsize_orddef(OS_32),false);
+           opsize:=S_L;
+         end
+       else
+         { TODO: support LOC_REFERENCE }
+         force_reg_left_right(true, true);
+
+        if (right.location.loc = LOC_CONSTANT) then
+          current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,opsize,
+            longint(right.location.value),left.location.register))
         else
-          { ToDo : zero/sign extend??? }
-          if tcgsize2size[right.location.size]<tcgsize2size[left.location.size] then
-            cmpsize:=left.location.size
-          else
-            cmpsize:=right.location.size;
-        opsize:=tcgsize2opsize[cmpsize];
-        if opsize=S_NO then
-          internalerror(2013090301);
-        { Attention: The RIGHT(!) operand is substracted from and must be a
-                     register! }
-        {if (right.location.loc = LOC_CONSTANT) then
-          if useconst then
-            current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,opsize,
-              longint(right.location.value),left.location.register))
-          else
-            begin
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,opsize,
-                tmpreg,left.location.register));
-            end
-        else}
           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,opsize,
             right.location.register,left.location.register));
      end;
@@ -326,6 +314,7 @@ implementation
     procedure t68kaddnode.second_cmp64bit;
       var
         unsigned : boolean;
+        href: treference;
 
       procedure firstjmp64bitcmp;
         var
@@ -385,17 +374,83 @@ implementation
         end;
 
       begin
+        { This puts constant operand (if any) to the right }
         pass_left_right;
-        force_reg_left_right(false,false);
 
         unsigned:=not(is_signed(left.resultdef)) or
                   not(is_signed(right.resultdef));
 
         location_reset(location,LOC_JUMP,OS_NO);
-        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi));
-        firstjmp64bitcmp;
-        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo));
-        secondjmp64bitcmp;
+
+        if (right.location.loc=LOC_CONSTANT) and (right.location.value64=0) and
+          (nodetype in [equaln,unequaln]) then
+          begin
+            case left.location.loc of
+              LOC_REFERENCE,
+              LOC_CREFERENCE:
+                begin
+                  href:=left.location.reference;
+                  tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+                  current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,S_L,href));
+                  firstjmp64bitcmp;
+                  inc(href.offset,4);
+                  current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,S_L,href));
+                  secondjmp64bitcmp;
+                  location_freetemp(current_asmdata.CurrAsmList,left.location);
+                end;
+            else
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,S_L,left.location.register64.reglo));
+              firstjmp64bitcmp;
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,S_L,left.location.register64.reghi));
+              secondjmp64bitcmp;
+            end;
+            exit;
+          end;
+
+        { left and right no register?  }
+        { then one must be demanded    }
+        if not (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+          begin
+            if not (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true)
+            else
+              begin
+                location_swap(left.location,right.location);
+                toggleflag(nf_swapped);
+              end;
+          end;
+
+        { left is now in register }
+        case right.location.loc of
+          LOC_REGISTER,LOC_CREGISTER:
+            begin
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi));
+              firstjmp64bitcmp;
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo));
+              secondjmp64bitcmp;
+            end;
+          LOC_REFERENCE,LOC_CREFERENCE:
+            begin
+              href:=right.location.reference;
+              tcg68k(cg).fixref(current_asmdata.CurrAsmList,href);
+              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_CMP,S_L,href,left.location.register64.reghi));
+              firstjmp64bitcmp;
+              inc(href.offset,4);
+              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_CMP,S_L,href,left.location.register64.reglo));
+              secondjmp64bitcmp;
+              location_freetemp(current_asmdata.CurrAsmList,right.location);
+            end;
+          LOC_CONSTANT:
+            begin
+              current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_L,aint(hi(right.location.value64)),left.location.register64.reghi));
+              firstjmp64bitcmp;
+              current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_L,aint(lo(right.location.value64)),left.location.register64.reglo));
+              secondjmp64bitcmp;
+            end;
+        else
+          InternalError(2014072501);
+        end;
      end;