소스 검색

+ optimized division by negative power of 2 constants in the i8086 code
generator as well

git-svn-id: trunk@37004 -

nickysn 8 년 전
부모
커밋
aa415bfc6b
1개의 변경된 파일11개의 추가작업 그리고 7개의 파일을 삭제
  1. 11 7
      compiler/i8086/n8086mat.pas

+ 11 - 7
compiler/i8086/n8086mat.pas

@@ -103,6 +103,7 @@ implementation
         e : smallint;
         d,l,r,s,m,a,n,t : word;
         m_low,m_high,j,k : dword;
+        invertsign: Boolean;
       begin
         secondpass(left);
         if codegenerror then
@@ -121,13 +122,14 @@ implementation
 
         if (nodetype=divn) and (right.nodetype=ordconstn) then
           begin
-            if ispowerof2(tordconstnode(right).value.svalue,power) then
+            if isabspowerof2(tordconstnode(right).value,power) then
               begin
                 { for signed numbers, the numerator must be adjusted before the
                   shift instruction, but not wih unsigned numbers! Otherwise,
                   "Cardinal($ffffffff) div 16" overflows! (JM) }
                 if is_signed(left.resultdef) Then
                   begin
+                    invertsign:=tordconstnode(right).value<0;
                     if (current_settings.optimizecputype > cpu_386) and
                        not(cs_opt_size in current_settings.optimizerswitches) then
                       { use a sequence without jumps, saw this in
@@ -136,17 +138,17 @@ implementation
                         { no jumps, but more operations }
                         hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
                         emit_reg_reg(A_MOV,S_W,hreg1,hreg2);
-                        if tordconstnode(right).value=2 then
+                        if power=1 then
                           begin
-                            {If the left value is negative, hreg2=(right value-1)=1, otherwise 0.}
+                            {If the left value is negative, hreg2=(1 shl power)-1=1, otherwise 0.}
                             cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_16,15,hreg2);
                           end
                         else
                           begin
                             {If the left value is negative, hreg2=$ffff, otherwise 0.}
                             cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_16,15,hreg2);
-                            {If negative, hreg2=right value-1, otherwise 0.}
-                            emit_const_reg(A_AND,S_W,tordconstnode(right).value.svalue-1,hreg2);
+                            {If negative, hreg2=(1 shl power)-1, otherwise 0.}
+                            emit_const_reg(A_AND,S_W,(aint(1) shl power)-1,hreg2);
                           end;
                         { add to the left value }
                         emit_reg_reg(A_ADD,S_W,hreg2,hreg1);
@@ -162,10 +164,12 @@ implementation
                         if power=1 then
                           emit_reg(A_INC,S_W,hreg1)
                         else
-                          emit_const_reg(A_ADD,S_W,tordconstnode(right).value.svalue-1,hreg1);
+                          emit_const_reg(A_ADD,S_W,(aint(1) shl power)-1,hreg1);
                         cg.a_label(current_asmdata.CurrAsmList,hl);
                         cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_16,power,hreg1);
-                      end
+                      end;
+                    if invertsign then
+                      emit_reg(A_NEG,S_W,hreg1);
                   end
                 else
                   cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_16,power,hreg1);