Browse Source

+ tcg64fppc.a_op64_const_reg_reg() and tcg64fppc.a_op64_reg_reg_reg()
* several fixes, most notably in a_load_reg_reg(): it didn't do any
conversion from smaller to larger sizes or vice versa
* some small optimizations

Jonas Maebe 23 years ago
parent
commit
e3cbc3cf22
1 changed files with 101 additions and 54 deletions
  1. 101 54
      compiler/powerpc/cgcpu.pas

+ 101 - 54
compiler/powerpc/cgcpu.pas

@@ -117,6 +117,8 @@ unit cgcpu;
      tcg64fppc = class(tcg64f32)
      tcg64fppc = class(tcg64f32)
        procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
        procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
        procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);override;
        procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);override;
+       procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;regsrc,regdst : tregister64);override;
+       procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);override;
      end;
      end;
 
 
 
 
@@ -316,11 +318,26 @@ const
      procedure tcgppc.a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);
      procedure tcgppc.a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);
 
 
        begin
        begin
-         if (reg1 <> reg2) then
-           list.concat(taicpu.op_reg_reg(A_MR,reg2,reg1));
+         if (reg1 <> reg2) or
+            not(size in [OS_32,OS_S32]) then
+           begin
+             case size of
+               OS_8:
+                 list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,
+                   reg2,reg1,0,31-8+1,31));
+               OS_S8:
+                 list.concat(taicpu.op_reg_reg(A_EXTSB,reg2,reg1));
+               OS_16:
+                 list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,
+                   reg2,reg1,0,31-16+1,31));
+               OS_S16:
+                 list.concat(taicpu.op_reg_reg(A_EXTSH,reg2,reg1));
+               OS_32,OS_S32:
+                 list.concat(taicpu.op_reg_reg(A_MR,reg2,reg1));
+             end;
+           end;
        end;
        end;
 
 
-
      procedure tcgppc.a_load_sym_ofs_reg(list: taasmoutput; const sym: tasmsymbol; ofs: longint; reg: tregister);
      procedure tcgppc.a_load_sym_ofs_reg(list: taasmoutput; const sym: tasmsymbol; ofs: longint; reg: tregister);
 
 
        begin
        begin
@@ -380,20 +397,7 @@ const
          scratch_register: TRegister;
          scratch_register: TRegister;
 
 
        begin
        begin
-         case op of
-           OP_DIV, OP_IDIV, OP_IMUL, OP_MUL, OP_ADD, OP_AND, OP_OR, OP_SUB,
-           OP_XOR:
-             a_op_const_reg_reg(list,op,OS_32,a,reg,reg);
-           OP_SHL,OP_SHR,OP_SAR:
-             begin
-               if (a and 31) <> 0 then
-                 list.concat(taicpu.op_reg_reg_const(
-                   TOpCG2AsmOpConstLo[op],reg,reg,a and 31));
-               if (a shr 5) <> 0 then
-                 internalError(68991);
-             end
-           else internalError(68992);
-         end;
+         a_op_const_reg_reg(list,op,OS_32,a,reg,reg);
        end;
        end;
 
 
 
 
@@ -408,15 +412,26 @@ const
                        size: tcgsize; a: aword; src, dst: tregister);
                        size: tcgsize; a: aword; src, dst: tregister);
       var
       var
         l1,l2: longint;
         l1,l2: longint;
-
-      var
         oplo, ophi: tasmop;
         oplo, ophi: tasmop;
         scratchreg: tregister;
         scratchreg: tregister;
-        useReg: boolean;
+        useReg, gotrlwi: boolean;
+
+
+        function try_lo_hi: boolean;
+          begin
+            result := false;
+            if (smallint(a) > 0) then
+              begin
+                list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
+                list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,a shr 16));
+                result := true;
+              end;
+          end;
 
 
       begin
       begin
         ophi := TOpCG2AsmOpConstHi[op];
         ophi := TOpCG2AsmOpConstHi[op];
         oplo := TOpCG2AsmOpConstLo[op];
         oplo := TOpCG2AsmOpConstLo[op];
+        gotrlwi := get_rlwi_const(a,l1,l2);
         { constants in a PPC instruction are always interpreted as signed }
         { constants in a PPC instruction are always interpreted as signed }
         { 16bit values, so if the value is between low(smallint) and      }
         { 16bit values, so if the value is between low(smallint) and      }
         { high(smallint), it's easy                                       }
         { high(smallint), it's easy                                       }
@@ -438,15 +453,17 @@ const
             else if (longint(a) >= low(smallint)) and
             else if (longint(a) >= low(smallint)) and
                (longint(a) <= high(smallint)) and
                (longint(a) <= high(smallint)) and
                (not(op = OP_AND) or
                (not(op = OP_AND) or
-                not get_rlwi_const(a,l1,l2)) then
+                not gotrlwi) then
               begin
               begin
                 list.concat(taicpu.op_reg_reg_const(oplo,dst,src,a));
                 list.concat(taicpu.op_reg_reg_const(oplo,dst,src,a));
                 exit;
                 exit;
               end;
               end;
             { all basic constant instructions also have a shifted form that }
             { all basic constant instructions also have a shifted form that }
-            { works only on the highest 16bits, so if low(a) is 0, we can   }
+            { works only on the highest 16bits, so if lo(a) is 0, we can    }
             { use that one                                                  }
             { use that one                                                  }
-            if (lo(a) = 0) then
+            if (word(a) = 0) and
+               (not(op = OP_AND) or
+                not gotrlwi) then
               begin
               begin
                 list.concat(taicpu.op_reg_reg_const(ophi,dst,src,hi(a)));
                 list.concat(taicpu.op_reg_reg_const(ophi,dst,src,hi(a)));
                 exit;
                 exit;
@@ -456,21 +473,23 @@ const
         { operation                                                 }
         { operation                                                 }
         useReg := false;
         useReg := false;
         case op of
         case op of
-           OP_DIV, OP_IDIV, OP_IMUL, OP_MUL:
-             if (Op = OP_IMUL) and (longint(a) >= -32768) and
-                (longint(a) <= 32767) then
+          OP_DIV,OP_IDIV:
+            useReg := true;
+           OP_IMUL, OP_MUL:
+             if (longint(a) >= low(smallint)) and
+                (longint(a) <= high(smallint)) then
                list.concat(taicpu.op_reg_reg_const(A_MULLI,dst,src,a))
                list.concat(taicpu.op_reg_reg_const(A_MULLI,dst,src,a))
              else
              else
                usereg := true;
                usereg := true;
           OP_ADD,OP_SUB:
           OP_ADD,OP_SUB:
             begin
             begin
-              list.concat(taicpu.op_reg_reg_const(oplo,dst,src,low(a)));
+              list.concat(taicpu.op_reg_reg_const(oplo,dst,src,smallint(a)));
               list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,
               list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,
-                high(a) + ord(smallint(a) < 0)));
+                (a shr 16) + ord(smallint(a) < 0)));
             end;
             end;
           OP_OR:
           OP_OR:
             { try to use rlwimi }
             { try to use rlwimi }
-            if get_rlwi_const(a,l1,l2) then
+            if gotrlwi then
               begin
               begin
                 if src <> dst then
                 if src <> dst then
                   list.concat(taicpu.op_reg_reg(A_MR,dst,src));
                   list.concat(taicpu.op_reg_reg(A_MR,dst,src));
@@ -480,17 +499,18 @@ const
                   scratchreg,0,l1,l2));
                   scratchreg,0,l1,l2));
                 free_scratch_reg(list,scratchreg);
                 free_scratch_reg(list,scratchreg);
               end
               end
-            else
+            else if not try_lo_hi then
               useReg := true;
               useReg := true;
           OP_AND:
           OP_AND:
             { try to use rlwinm }
             { try to use rlwinm }
-            if get_rlwi_const(a,l1,l2) then
+            if gotrlwi then
               list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,dst,
               list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,dst,
                 src,0,l1,l2))
                 src,0,l1,l2))
             else
             else
               useReg := true;
               useReg := true;
           OP_XOR:
           OP_XOR:
-            useReg := true;
+            if not try_lo_hi then
+              usereg := true;
           OP_SHL,OP_SHR,OP_SAR:
           OP_SHL,OP_SHR,OP_SAR:
             begin
             begin
               if (a and 31) <> 0 Then
               if (a and 31) <> 0 Then
@@ -1172,6 +1192,8 @@ const
 
 
       begin
       begin
         get_rlwi_const := false;
         get_rlwi_const := false;
+        if (a = 0) or (a = $ffffffff) then
+          exit;
         { start with the lowest bit }
         { start with the lowest bit }
         testbit := 1;
         testbit := 1;
         { check its value }
         { check its value }
@@ -1226,6 +1248,7 @@ const
         get_rlwi_const := true;
         get_rlwi_const := true;
       end;
       end;
 
 
+
     procedure tcgppc.a_load_store(list:taasmoutput;op: tasmop;reg:tregister;
     procedure tcgppc.a_load_store(list:taasmoutput;op: tasmop;reg:tregister;
        ref: treference);
        ref: treference);
 
 
@@ -1240,7 +1263,6 @@ const
             reference_reset(tmpref);
             reference_reset(tmpref);
             tmpref.symbol := ref.symbol;
             tmpref.symbol := ref.symbol;
             tmpref.symaddr := refs_ha;
             tmpref.symaddr := refs_ha;
-//            tmpref.is_immediate := true;
             if ref.base <> R_NO then
             if ref.base <> R_NO then
               list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
               list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
                 ref.base,tmpref))
                 ref.base,tmpref))
@@ -1270,78 +1292,97 @@ const
 
 
 
 
     procedure tcg64fppc.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
     procedure tcg64fppc.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
+      begin
+        a_op64_reg_reg_reg(list,op,regsrc,regdst,regdst);
+      end;
 
 
+
+    procedure tcg64fppc.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
+      begin
+        a_op64_const_reg_reg(list,op,value,reg,reg);
+      end;
+
+
+    procedure tcg64fppc.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
       begin
       begin
         case op of
         case op of
           OP_AND,OP_OR,OP_XOR:
           OP_AND,OP_OR,OP_XOR:
             begin
             begin
-              cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
-              cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
+              cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+              cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
             end;
             end;
           OP_ADD:
           OP_ADD:
             begin
             begin
-              list.concat(taicpu.op_reg_reg_reg(A_ADDC,regdst.reglo,regsrc.reglo,regdst.reglo));
-              list.concat(taicpu.op_reg_reg_reg(A_ADDE,regdst.reghi,regsrc.reghi,regdst.reghi));
+              list.concat(taicpu.op_reg_reg_reg(A_ADDC,regdst.reglo,regsrc1.reglo,regsrc2.reglo));
+              list.concat(taicpu.op_reg_reg_reg(A_ADDE,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
             end;
             end;
           OP_SUB:
           OP_SUB:
             begin
             begin
-              list.concat(taicpu.op_reg_reg_reg(A_SUBC,regdst.reglo,regdst.reglo,regsrc.reglo));
-              list.concat(taicpu.op_reg_reg_reg(A_SUBFE,regdst.reghi,regsrc.reghi,regdst.reghi));
+              list.concat(taicpu.op_reg_reg_reg(A_SUBC,regdst.reglo,regsrc2.reglo,regsrc1.reglo));
+              list.concat(taicpu.op_reg_reg_reg(A_SUBFE,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
             end;
             end;
+          else
+            internalerror(2002072801);
         end;
         end;
       end;
       end;
 
 
-    procedure tcg64fppc.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
+
+    procedure tcg64fppc.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;regsrc,regdst : tregister64);
 
 
       const
       const
         ops: array[boolean,1..3] of tasmop = ((A_ADDIC,A_ADDC,A_ADDZE),
         ops: array[boolean,1..3] of tasmop = ((A_ADDIC,A_ADDC,A_ADDZE),
                                               (A_SUBIC,A_SUBC,A_ADDME));
                                               (A_SUBIC,A_SUBC,A_ADDME));
-
       var
       var
         tmpreg: tregister;
         tmpreg: tregister;
         tmpreg64: tregister64;
         tmpreg64: tregister64;
-        isadd: boolean;
+        issub: boolean;
       begin
       begin
         case op of
         case op of
           OP_AND,OP_OR,OP_XOR:
           OP_AND,OP_OR,OP_XOR:
             begin
             begin
-              cg.a_op_const_reg(list,op,cardinal(value),reg.reglo);
-              cg.a_op_const_reg(list,op,value shr 32,reg.reghi);
+              cg.a_op_const_reg_reg(list,op,OS_32,cardinal(value),regsrc.reglo,regdst.reglo);
+              cg.a_op_const_reg_reg(list,op,OS_32,value shr 32,regsrc.reghi,
+                regdst.reghi);
             end;
             end;
           OP_ADD, OP_SUB:
           OP_ADD, OP_SUB:
             begin
             begin
               if (longint(value) <> 0) then
               if (longint(value) <> 0) then
                 begin
                 begin
-                  isadd := op = OP_ADD;
+                  issub := op = OP_SUB;
                   if (longint(value) >= -32768) and
                   if (longint(value) >= -32768) and
                      (longint(value) <= 32767) then
                      (longint(value) <= 32767) then
                     begin
                     begin
-                      list.concat(taicpu.op_reg_reg_const(ops[isadd,1],
-                        reg.reglo,reg.reglo,aword(value)));
+                      list.concat(taicpu.op_reg_reg_const(ops[issub,1],
+                        regdst.reglo,regsrc.reglo,aword(value)));
+                      list.concat(taicpu.op_reg_reg(ops[issub,3],
+                        regdst.reghi,regsrc.reghi));
                     end
                     end
                   else if ((value shr 32) = 0) then
                   else if ((value shr 32) = 0) then
                     begin
                     begin
                       tmpreg := cg.get_scratch_reg_int(list);
                       tmpreg := cg.get_scratch_reg_int(list);
                       cg.a_load_const_reg(list,OS_32,cardinal(value),tmpreg);
                       cg.a_load_const_reg(list,OS_32,cardinal(value),tmpreg);
-                      list.concat(taicpu.op_reg_reg_reg(ops[isadd,2],
-                        reg.reglo,reg.reglo,tmpreg));
-                      list.concat(taicpu.op_reg_reg(ops[isadd,3],
-                        reg.reghi,reg.reghi));
+                      list.concat(taicpu.op_reg_reg_reg(ops[issub,2],
+                        regdst.reglo,regsrc.reglo,tmpreg));
                       cg.free_scratch_reg(list,tmpreg);
                       cg.free_scratch_reg(list,tmpreg);
+                      list.concat(taicpu.op_reg_reg(ops[issub,3],
+                        regdst.reghi,regsrc.reghi));
                     end
                     end
                   else
                   else
                     begin
                     begin
                       tmpreg64.reglo := cg.get_scratch_reg_int(list);
                       tmpreg64.reglo := cg.get_scratch_reg_int(list);
                       tmpreg64.reghi := cg.get_scratch_reg_int(list);
                       tmpreg64.reghi := cg.get_scratch_reg_int(list);
                       a_load64_const_reg(list,value,tmpreg64);
                       a_load64_const_reg(list,value,tmpreg64);
-                      a_op64_reg_reg(list,op,tmpreg64,reg);
+                      a_op64_reg_reg_reg(list,op,tmpreg64,regsrc,regdst);
                       cg.free_scratch_reg(list,tmpreg64.reghi);
                       cg.free_scratch_reg(list,tmpreg64.reghi);
                       cg.free_scratch_reg(list,tmpreg64.reglo);
                       cg.free_scratch_reg(list,tmpreg64.reglo);
                     end
                     end
                 end
                 end
               else
               else
-                cg.a_op_const_reg(list,op,value shr 32,reg.reghi);
+                cg.a_op_const_reg_reg(list,op,OS_32,value shr 32,regsrc.reghi,
+                  regdst.reghi);
             end;
             end;
+          else
+            internalerror(2002072802);
         end;
         end;
       end;
       end;
 
 
@@ -1352,7 +1393,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.26  2002-07-27 19:59:29  jonas
+  Revision 1.27  2002-07-28 16:01:59  jonas
+    + tcg64fppc.a_op64_const_reg_reg() and tcg64fppc.a_op64_reg_reg_reg()
+    * several fixes, most notably in a_load_reg_reg(): it didn't do any
+      conversion from smaller to larger sizes or vice versa
+    * some small optimizations
+
+  Revision 1.26  2002/07/27 19:59:29  jonas
     * fixed a_loadaddr_ref_reg()
     * fixed a_loadaddr_ref_reg()
     * fixed g_flags2reg()
     * fixed g_flags2reg()
     * optimized g_concatcopy()
     * optimized g_concatcopy()