Ver código fonte

+ initial a_op_const_reg_reg and a_op_reg_reg_reg implementations to generate optimized 16 Bit multiplications on avr

git-svn-id: trunk@30648 -
florian 10 anos atrás
pai
commit
9e51283ae0
1 arquivos alterados com 58 adições e 1 exclusões
  1. 58 1
      compiler/avr/cgcpu.pas

+ 58 - 1
compiler/avr/cgcpu.pas

@@ -57,6 +57,8 @@ unit cgcpu;
 
         procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
         procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
+        procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
+        procedure a_op_const_reg_reg(list : TAsmList;op : TOpCg;size : tcgsize; a : tcgint;src,dst : tregister); override;
 
         { move instructions }
         procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
@@ -426,6 +428,47 @@ unit cgcpu;
        end;
 
 
+     procedure tcgavr.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
+       begin
+         if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16]) then
+           begin
+             getcpuregister(list,NR_R0);
+             getcpuregister(list,NR_R1);
+             list.concat(taicpu.op_reg_reg(A_MUL,src1,src2));
+             emit_mov(list,dst,NR_R0);
+             emit_mov(list,GetNextReg(dst),NR_R1);
+             list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(src1),src2));
+             list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
+             list.concat(taicpu.op_reg_reg(A_MUL,src1,GetNextReg(src2)));
+             list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
+             ungetcpuregister(list,NR_R0);
+             list.concat(taicpu.op_reg(A_CLR,NR_R1));
+             ungetcpuregister(list,NR_R1);
+           end
+         else
+          inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+       end;
+
+
+     procedure tcgavr.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
+       begin
+         if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16]) and (a in [1,2,4,8]) then
+           begin
+             emit_mov(list,dst,src);
+             emit_mov(list,GetNextReg(dst),GetNextReg(src));
+             a:=a shr 1;
+             while a>0 do
+               begin
+                 list.concat(taicpu.op_reg(A_LSL,dst));
+                 list.concat(taicpu.op_reg(A_ROL,GetNextReg(dst)));
+                 a:=a shr 1;
+               end;
+           end
+         else
+           inherited a_op_const_reg_reg(list,op,size,a,src,dst);
+       end;
+
+
      procedure tcgavr.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
        var
          countreg,
@@ -543,6 +586,19 @@ unit cgcpu;
                  end
                else if size=OS_16 then
                  begin
+                   tmpreg:=getintregister(list,OS_16);
+                   emit_mov(list,tmpreg,dst);
+                   emit_mov(list,GetNextReg(tmpreg),GetNextReg(dst));
+                   list.concat(taicpu.op_reg_reg(A_MUL,tmpreg,src));
+                   emit_mov(list,dst,NR_R0);
+                   emit_mov(list,GetNextReg(dst),NR_R1);
+                   list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(tmpreg),src));
+                   list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
+                   list.concat(taicpu.op_reg_reg(A_MUL,tmpreg,GetNextReg(src)));
+                   list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
+                   list.concat(taicpu.op_reg(A_CLR,NR_R1));
+
+                   { keep code for muls with overflow checking
                    pd:=search_system_proc('fpc_mul_word');
                    paraloc1.init;
                    paraloc2.init;
@@ -568,6 +624,7 @@ unit cgcpu;
                    paraloc3.done;
                    paraloc2.done;
                    paraloc1.done;
+                   }
                  end
                else
                  internalerror(2011022002);
@@ -1751,7 +1808,7 @@ unit cgcpu;
             cg.a_label(list,l);
             list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
             list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
-            a_op_const_reg(list,OP_SUB,countregsize,1,countreg);
+            list.concat(taicpu.op_reg(A_DEC,countreg));
             a_jmp_flags(list,F_NE,l);
             // keep registers alive
             list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));