浏览代码

* patch by J. Gareth Moreton:
- Moved the part that emits the CMOV command outside of the if-else block, because it's the same in both branches and was just duplicated code.
- Moved a comment about powers of 2 to be right before the correct if-else block.
- Added a couple of comments to explain what the algorithm is doing to obtain the remainder.
- Added missing "writeln('ok');" (since 'tmoddiv3.pp' has it) and program header to 'tmoddiv4.pp'.
- Changed program name from "testfile2" to "tmoddiv3" in 'tmoddiv3.pp'.

git-svn-id: trunk@37939 -

florian 7 年之前
父节点
当前提交
11a3d8762a
共有 3 个文件被更改,包括 15 次插入15 次删除
  1. 12 14
      compiler/x86/nx86mat.pas
  2. 1 1
      tests/test/cg/tmoddiv3.pp
  3. 2 0
      tests/test/cg/tmoddiv4.pp

+ 12 - 14
compiler/x86/nx86mat.pas

@@ -524,9 +524,9 @@ interface
                   end;
                   end;
               end;
               end;
           end
           end
-        { unsigned modulus by a (+/-)power-of-2 constant? }
         else if (nodetype=modn) and (right.nodetype=ordconstn) and not(is_signed(left.resultdef)) then
         else if (nodetype=modn) and (right.nodetype=ordconstn) and not(is_signed(left.resultdef)) then
           begin
           begin
+            { unsigned modulus by a (+/-)power-of-2 constant? }
             if isabspowerof2(tordconstnode(right).value,power) then
             if isabspowerof2(tordconstnode(right).value,power) then
               begin
               begin
                 emit_const_reg(A_AND,opsize,(aint(1) shl power)-1,hreg1);
                 emit_const_reg(A_AND,opsize,(aint(1) shl power)-1,hreg1);
@@ -554,12 +554,6 @@ interface
                         emit_reg_reg(A_XOR,opsize,location.register,location.register);
                         emit_reg_reg(A_XOR,opsize,location.register,location.register);
                         cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         emit_reg_reg(A_CMP,opsize,hreg2,hreg1);
                         emit_reg_reg(A_CMP,opsize,hreg2,hreg1);
-
-                        { Emit conditional move that depends on the carry flag }
-                        instr:=TAiCpu.op_reg_reg(A_CMOVcc,opsize,hreg3,location.register);
-                        instr.condition := C_AE;
-                        current_asmdata.CurrAsmList.concat(instr);
-                        cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                       end
                       end
                     else
                     else
                       begin
                       begin
@@ -568,14 +562,15 @@ interface
 
 
                         cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         emit_const_reg(A_CMP,opsize,aint(d),hreg1);
                         emit_const_reg(A_CMP,opsize,aint(d),hreg1);
-
-                        { Emit conditional move that depends on the carry flag }
-                        instr:=TAiCpu.op_reg_reg(A_CMOVcc,opsize,hreg3,location.register);
-                        instr.condition := C_AE;
-                        current_asmdata.CurrAsmList.concat(instr);
-                        cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                       end;
                       end;
 
 
+                    { Emit conditional move that depends on the carry flag being zero,
+                      that is, the comparison result is above or equal }
+                    instr:=TAiCpu.op_reg_reg(A_CMOVcc,opsize,hreg3,location.register);
+                    instr.condition := C_AE;
+                    current_asmdata.CurrAsmList.concat(instr);
+                    cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+
                     emit_reg_reg(A_ADD,opsize,hreg1,location.register);
                     emit_reg_reg(A_ADD,opsize,hreg1,location.register);
                   end
                   end
                 else
                 else
@@ -600,8 +595,11 @@ interface
                         dec(s);
                         dec(s);
                       end;
                       end;
                     if s<>0 then
                     if s<>0 then
-                      emit_const_reg(A_SHR,opsize,aint(s),regd);
+                      emit_const_reg(A_SHR,opsize,aint(s),regd); { R/EDX now contains the quotient }
 
 
+                    { Now multiply the quotient by the original denominator and
+                      subtract the product from the original numerator to get
+                      the remainder. }
                     if (cgsize in [OS_64,OS_S64]) then { Cannot use 64-bit constants in IMUL }
                     if (cgsize in [OS_64,OS_S64]) then { Cannot use 64-bit constants in IMUL }
                       begin
                       begin
                         hreg3:=cg.getintregister(current_asmdata.CurrAsmList,cgsize);
                         hreg3:=cg.getintregister(current_asmdata.CurrAsmList,cgsize);

+ 1 - 1
tests/test/cg/tmoddiv3.pp

@@ -1,4 +1,4 @@
-program testfile2;
+program tmoddiv3;
 
 
 const
 const
   TestValues: array[0..9] of LongWord = (500, 1, 0, 995, $7FFFFFFF, $80000000, $80000001, $80000002, $FFFFFFFF, 1000000);
   TestValues: array[0..9] of LongWord = (500, 1, 0, 995, $7FFFFFFF, $80000000, $80000001, $80000002, $FFFFFFFF, 1000000);

+ 2 - 0
tests/test/cg/tmoddiv4.pp

@@ -1,3 +1,4 @@
+program tmoddiv4;
 
 
 const
 const
   TestValues: array[0..10] of QWord = (500, 1, 0, 995, $100000000, $100000001, $7FFFFFFFFFFFFFFF, QWord($8000000000000000), QWord($8000000000000001), QWord($8000000000000002), 1000000);
   TestValues: array[0..10] of QWord = (500, 1, 0, 995, $100000000, $100000001, $7FFFFFFFFFFFFFFF, QWord($8000000000000000), QWord($8000000000000001), QWord($8000000000000002), 1000000);
@@ -107,4 +108,5 @@ begin
     Writeln(Y);
     Writeln(Y);
     DoCheck;
     DoCheck;
   end;
   end;
+  writeln('ok');
 end.
 end.