Răsfoiți Sursa

* added missing masking of upper 24/16 bits on ppc after performing
add/sub/shl/mul on 8 or 16 bit "registers" + test (tcinvint5)
* optimized register-register loading of < 32 bit values (removes
30KB of superfluous extsb/extsh/rlwinm's from compiler+rtl)

git-svn-id: trunk@3207 -

Jonas Maebe 19 ani în urmă
părinte
comite
0d77459b9d
3 a modificat fișierele cu 123 adăugiri și 17 ștergeri
  1. 1 0
      .gitattributes
  2. 64 17
      compiler/powerpc/cgcpu.pas
  3. 58 0
      tests/test/cg/tcnvint5.pp

+ 1 - 0
.gitattributes

@@ -5538,6 +5538,7 @@ tests/test/cg/tcnvint1.pp svneol=native#text/plain
 tests/test/cg/tcnvint2.pp svneol=native#text/plain
 tests/test/cg/tcnvint2.pp svneol=native#text/plain
 tests/test/cg/tcnvint3.pp svneol=native#text/plain
 tests/test/cg/tcnvint3.pp svneol=native#text/plain
 tests/test/cg/tcnvint4.pp svneol=native#text/plain
 tests/test/cg/tcnvint4.pp svneol=native#text/plain
+tests/test/cg/tcnvint5.pp svneol=native#text/plain
 tests/test/cg/tcnvptr.pp svneol=native#text/plain
 tests/test/cg/tcnvptr.pp svneol=native#text/plain
 tests/test/cg/tcnvset.pp svneol=native#text/plain
 tests/test/cg/tcnvset.pp svneol=native#text/plain
 tests/test/cg/tcnvstr1.pp svneol=native#text/plain
 tests/test/cg/tcnvstr1.pp svneol=native#text/plain

+ 64 - 17
compiler/powerpc/cgcpu.pas

@@ -105,6 +105,9 @@ unit cgcpu;
         (* NOT IN USE: *)
         (* NOT IN USE: *)
         procedure g_return_from_proc_mac(list : TAsmList;parasize : aint);
         procedure g_return_from_proc_mac(list : TAsmList;parasize : aint);
 
 
+        { clear out potential overflow bits from 8 or 16 bit operations  }
+        { the upper 24/16 bits of a register after an operation          }
+        procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 
 
         { Make sure ref is a valid reference for the PowerPC and sets the }
         { Make sure ref is a valid reference for the PowerPC and sets the }
         { base to the value of the index if (base = R_NO).                }
         { base to the value of the index if (base = R_NO).                }
@@ -516,21 +519,30 @@ const
        var
        var
          instr: taicpu;
          instr: taicpu;
        begin
        begin
-         case tosize of
-           OS_8:
-             instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
-               reg2,reg1,0,31-8+1,31);
-           OS_S8:
-             instr := taicpu.op_reg_reg(A_EXTSB,reg2,reg1);
-           OS_16:
-             instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
-               reg2,reg1,0,31-16+1,31);
-           OS_S16:
-             instr := taicpu.op_reg_reg(A_EXTSH,reg2,reg1);
-           OS_32,OS_S32:
-             instr := taicpu.op_reg_reg(A_MR,reg2,reg1);
-           else internalerror(2002090901);
-         end;
+         if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
+            ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
+             (fromsize <> tosize)) or
+            { needs to mask out the sign in the top 16 bits }
+            ((fromsize = OS_S8) and
+             (tosize = OS_16)) then
+           case tosize of
+             OS_8:
+               instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
+                 reg2,reg1,0,31-8+1,31);
+             OS_S8:
+               instr := taicpu.op_reg_reg(A_EXTSB,reg2,reg1);
+             OS_16:
+               instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
+                 reg2,reg1,0,31-16+1,31);
+             OS_S16:
+               instr := taicpu.op_reg_reg(A_EXTSH,reg2,reg1);
+             OS_32,OS_S32:
+               instr := taicpu.op_reg_reg(A_MR,reg2,reg1);
+             else internalerror(2002090901);
+           end
+         else
+           instr := taicpu.op_reg_reg(A_MR,reg2,reg1);
+           
          list.concat(instr);
          list.concat(instr);
          rg[R_INTREGISTER].add_move_instruction(instr);
          rg[R_INTREGISTER].add_move_instruction(instr);
        end;
        end;
@@ -611,6 +623,16 @@ const
          end;
          end;
 
 
 
 
+    procedure tcgppc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+      const
+        overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+      begin
+        if (op in overflowops) and
+           (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+          a_load_reg_reg(list,OS_32,size,dst,dst);
+      end;
+
+
     procedure tcgppc.a_op_const_reg_reg(list: TAsmList; op: TOpCg;
     procedure tcgppc.a_op_const_reg_reg(list: TAsmList; op: TOpCg;
                        size: tcgsize; a: aint; src, dst: tregister);
                        size: tcgsize; a: aint; src, dst: tregister);
       var
       var
@@ -651,9 +673,23 @@ const
               begin
               begin
                 case op of
                 case op of
                   OP_OR:
                   OP_OR:
-                    list.concat(taicpu.op_reg_const(A_LI,dst,-1));
+                    case size of
+                      OS_8, OS_S8:
+                        list.concat(taicpu.op_reg_const(A_LI,dst,255));
+                      OS_16, OS_S16:
+                        a_load_const_reg(list,OS_16,65535,dst);
+                      else
+                        list.concat(taicpu.op_reg_const(A_LI,dst,-1));
+                    end;
                   OP_XOR:
                   OP_XOR:
-                    list.concat(taicpu.op_reg_reg(A_NOT,dst,src));
+                    case size of
+                      OS_8, OS_S8:
+                        list.concat(taicpu.op_reg_reg_const(A_XORI,dst,src,255));
+                      OS_16, OS_S16:
+                        list.concat(taicpu.op_reg_reg_const(A_XORI,dst,src,65535));
+                      else
+                        list.concat(taicpu.op_reg_reg(A_NOT,dst,src));
+                    end;
                   OP_AND:
                   OP_AND:
                     a_load_reg_reg(list,size,size,src,dst);
                     a_load_reg_reg(list,size,size,src,dst);
                 end;
                 end;
@@ -663,7 +699,13 @@ const
                ((op <> OP_AND) or
                ((op <> OP_AND) or
                 not gotrlwi) then
                 not gotrlwi) then
               begin
               begin
+                if ((size = OS_8) and
+                    (byte(a) <> a)) or
+                   ((size = OS_S8) and
+                    (shortint(a) <> a)) then
+                  internalerror(200604142);
                 list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
                 list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
+                { and/or/xor -> cannot overflow in high 16 bits }
                 exit;
                 exit;
               end;
               end;
             { all basic constant instructions also have a shifted form that }
             { all basic constant instructions also have a shifted form that }
@@ -673,6 +715,8 @@ const
                (not(op = OP_AND) or
                (not(op = OP_AND) or
                 not gotrlwi) then
                 not gotrlwi) then
               begin
               begin
+                if (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+                  internalerror(200604141);
                 list.concat(taicpu.op_reg_reg_const(ophi,dst,src,word(a shr 16)));
                 list.concat(taicpu.op_reg_reg_const(ophi,dst,src,word(a shr 16)));
                 exit;
                 exit;
               end;
               end;
@@ -687,6 +731,7 @@ const
                   (a <= high(smallint)) then
                   (a <= high(smallint)) then
              begin
              begin
                list.concat(taicpu.op_reg_reg_const(A_ADDI,dst,src,smallint(a)));
                list.concat(taicpu.op_reg_reg_const(A_ADDI,dst,src,smallint(a)));
+               maybeadjustresult(list,op,size,dst);
                exit;
                exit;
              end;
              end;
 
 
@@ -783,6 +828,7 @@ const
             a_load_const_reg(list,OS_32,a,scratchreg);
             a_load_const_reg(list,OS_32,a,scratchreg);
             a_op_reg_reg_reg(list,op,OS_32,scratchreg,src,dst);
             a_op_reg_reg_reg(list,op,OS_32,scratchreg,src,dst);
           end;
           end;
+        maybeadjustresult(list,op,size,dst);
       end;
       end;
 
 
 
 
@@ -809,6 +855,7 @@ const
            else
            else
              list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
              list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
          end;
          end;
+         maybeadjustresult(list,op,size,dst);
        end;
        end;
 
 
 
 

+ 58 - 0
tests/test/cg/tcnvint5.pp

@@ -0,0 +1,58 @@
+var
+  error: boolean;
+
+procedure test;
+var
+  b: byte;
+  l: longint;
+begin
+  b := 254;
+  inc(b,2);
+  l := b;
+  if (l <> 0) then
+    begin
+      writeln('overflow error with byte');
+      error := true;
+    end;
+
+  b :=1;
+  dec(b,2);
+  l := b;
+  if (l <> 255) then
+    begin
+      writeln('underflow error with byte');
+      error := true;
+    end;
+end;
+
+
+procedure test2;
+var
+  b: shortint;
+  l: longint;
+begin
+  b := -127;
+  dec(b,2);
+  l := b;
+  if (l <> 127) then
+    begin
+      writeln('neg error with shortint');
+      error := true;
+    end;
+
+  b := 126;
+  inc(b,2);
+  l := b;
+  if (l <> -128) then
+    begin
+      writeln('pos error with shortint');
+      error := true;
+    end;
+end;
+
+begin
+  error := false;
+  test;
+  test2;
+  halt(ord(error));
+end.