瀏覽代碼

* refactored the code generation for 32-bit rol/ror by const for i8086, so it
uses less code repetition and allow choosing various methods (some of which
will be implemented later and selected, according to the cpu and optimization
settings (size vs speed))

git-svn-id: trunk@35743 -

nickysn 8 年之前
父節點
當前提交
0fd860d9e7
共有 1 個文件被更改,包括 60 次插入31 次删除
  1. 60 31
      compiler/i8086/cgcpu.pas

+ 60 - 31
compiler/i8086/cgcpu.pas

@@ -253,6 +253,9 @@ unit cgcpu;
 
     procedure tcg8086.a_op_const_reg(list: TAsmList; Op: TOpCG; size: TCGSize;
       a: tcgint; reg: TRegister);
+      type
+        trox32method=(rm_unspecified,rm_unrolledleftloop,rm_unrolledrightloop,
+                      rm_loopleft,rm_loopright,rm_fast_386);
       var
         tmpreg: tregister;
         op1, op2: TAsmOp;
@@ -261,7 +264,9 @@ unit cgcpu;
         ai: taicpu;
         use_loop, use_186_fast_shift, use_8086_fast_shift,
           use_386_fast_shift: Boolean;
+        rox32method: trox32method=rm_unspecified;
         i: Integer;
+        rol_amount, ror_amount: TCGInt;
       begin
         optimize_op_const(size, op, a);
         check_register_size(size,reg);
@@ -565,40 +570,64 @@ unit cgcpu;
               OP_ROL,OP_ROR:
                 begin
                   a:=a and 31;
-                  if a=16 then
-                    list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)))
-                  else if ((a=1) and (op=OP_ROL)) or ((a=31) and (op=OP_ROR)) then
-                    begin
-                      list.Concat(taicpu.op_const_reg(A_SHL,S_W,1,GetNextReg(reg)));
-                      list.Concat(taicpu.op_const_reg(A_RCL,S_W,1,reg));
-                      list.Concat(taicpu.op_const_reg(A_ADC,S_W,0,GetNextReg(reg)));
-                    end
-                  else if ((a=15) and (op=OP_ROL)) or ((a=31) and (op=OP_ROR)) then
-                    begin
-                      list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
-                      tmpreg:=getintregister(list,OS_16);
-                      a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
-                      list.Concat(taicpu.op_const_reg(A_SHR,S_W,1,tmpreg));
-                      list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,GetNextReg(reg)));
-                      list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
-                    end
-                  else if ((a=17) and (op=OP_ROL)) or ((a=31) and (op=OP_ROR)) then
-                    begin
-                      list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
-                      list.Concat(taicpu.op_const_reg(A_SHL,S_W,1,GetNextReg(reg)));
-                      list.Concat(taicpu.op_const_reg(A_RCL,S_W,1,reg));
-                      list.Concat(taicpu.op_const_reg(A_ADC,S_W,0,GetNextReg(reg)));
-                    end
-                  else if ((a=31) and (op=OP_ROL)) or ((a=1) and (op=OP_ROR)) then
+                  if a=0 then
+                    exit;
+                  if op=OP_ROL then
                     begin
-                      tmpreg:=getintregister(list,OS_16);
-                      a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
-                      list.Concat(taicpu.op_const_reg(A_SHR,S_W,1,tmpreg));
-                      list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,GetNextReg(reg)));
-                      list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
+                      rol_amount:=a;
+                      ror_amount:=32-a;
                     end
                   else
-                    internalerror(2017040501);
+                    begin
+                      rol_amount:=32-a;
+                      ror_amount:=a;
+                    end;
+                  case rol_amount of
+                    1: rox32method:=rm_unrolledleftloop;
+                    15: rox32method:=rm_unrolledrightloop;
+                    16: rox32method:=rm_unrolledleftloop;
+                    17: rox32method:=rm_unrolledrightloop;
+                    31: rox32method:=rm_unrolledrightloop;
+                    else
+                      internalerror(2017040601);
+                  end;
+                  case rox32method of
+                    rm_unrolledleftloop:
+                      begin
+                        if rol_amount>=16 then
+                          begin
+                            list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
+                            dec(rol_amount,16);
+                          end;
+                        for i:=1 to rol_amount do
+                          begin
+                            list.Concat(taicpu.op_const_reg(A_SHL,S_W,1,GetNextReg(reg)));
+                            list.Concat(taicpu.op_const_reg(A_RCL,S_W,1,reg));
+                            list.Concat(taicpu.op_const_reg(A_ADC,S_W,0,GetNextReg(reg)));
+                          end;
+                      end;
+                    rm_unrolledrightloop:
+                      begin
+                        if ror_amount>=16 then
+                          begin
+                            list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
+                            dec(ror_amount,16);
+                          end;
+                        tmpreg:=getintregister(list,OS_16);
+                        for i:=1 to ror_amount do
+                          begin
+                            a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
+                            list.Concat(taicpu.op_const_reg(A_SHR,S_W,1,tmpreg));
+                            list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,GetNextReg(reg)));
+                            list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
+                          end;
+                      end;
+                    rm_loopleft,rm_loopright,rm_fast_386:
+                      {todo: implement the other methods}
+                      internalerror(2017040603);
+                    else
+                      internalerror(2017040602);
+                  end;
                 end;
               else
                 begin