mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 06:59:33 +01:00 
			
		
		
		
	* make use of lea if possible
git-svn-id: trunk@25898 -
This commit is contained in:
		
							parent
							
								
									945b318012
								
							
						
					
					
						commit
						3c58cad96b
					
				@ -70,6 +70,9 @@ unit cgx86;
 | 
			
		||||
        procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
 | 
			
		||||
        procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
 | 
			
		||||
 | 
			
		||||
        procedure a_op_const_reg_reg(list : TAsmList; op : Topcg; size : Tcgsize; a : tcgint; src,dst : Tregister); override;
 | 
			
		||||
        procedure a_op_reg_reg_reg(list : TAsmList; op : TOpCg; size : tcgsize; src1,src2,dst : tregister); override;
 | 
			
		||||
 | 
			
		||||
        { move instructions }
 | 
			
		||||
        procedure a_load_const_reg(list : TAsmList; tosize: tcgsize; a : tcgint;reg : tregister);override;
 | 
			
		||||
        procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
 | 
			
		||||
@ -1547,11 +1550,71 @@ unit cgx86;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    procedure tcgx86.a_op_const_reg_reg(list:TAsmList;op:Topcg;size:Tcgsize;
 | 
			
		||||
                                        a:tcgint;src,dst:Tregister);
 | 
			
		||||
      var
 | 
			
		||||
        power  : longint;
 | 
			
		||||
        href : treference;
 | 
			
		||||
      begin
 | 
			
		||||
      {  if (op in [OP_MUL,OP_IMUL]) and (size in [OS_32,OS_S32,OS_64,OS_S64]) and
 | 
			
		||||
          not(cs_check_overflow in current_settings.localswitches) and
 | 
			
		||||
          (a>1) and ispowerof2(int64(a-1),power) and (power in [1..3]) then
 | 
			
		||||
          begin
 | 
			
		||||
            reference_reset_base(href,src,0,0);
 | 
			
		||||
            href.index:=src;
 | 
			
		||||
            href.scalefactor:=a-1;
 | 
			
		||||
            list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
 | 
			
		||||
          end
 | 
			
		||||
        else } if (op=OP_ADD) and
 | 
			
		||||
          ((size in [OS_32,OS_S32]) or
 | 
			
		||||
           { lea supports only 32 bit signed displacments }
 | 
			
		||||
           ((size=OS_64) and (a>=0) and (a<=maxLongint)) or
 | 
			
		||||
           ((size=OS_S64) and (a>=-maxLongint) and (a<=maxLongint))
 | 
			
		||||
          ) and
 | 
			
		||||
          not(cs_check_overflow in current_settings.localswitches) then
 | 
			
		||||
          begin
 | 
			
		||||
            reference_reset_base(href,src,a,0);
 | 
			
		||||
            list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
 | 
			
		||||
          end
 | 
			
		||||
        else if (op=OP_SUB) and
 | 
			
		||||
          ((size in [OS_32,OS_S32]) or
 | 
			
		||||
           { lea supports only 32 bit signed displacments }
 | 
			
		||||
           ((size=OS_64) and (a>=0) and (a<=maxLongint)) or
 | 
			
		||||
           ((size=OS_S64) and (a>=-maxLongint) and (a<=maxLongint))
 | 
			
		||||
          ) and
 | 
			
		||||
          not(cs_check_overflow in current_settings.localswitches) then
 | 
			
		||||
          begin
 | 
			
		||||
            reference_reset_base(href,src,-a,0);
 | 
			
		||||
            list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          inherited a_op_const_reg_reg(list,op,size,a,src,dst);
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    procedure tcgx86.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
 | 
			
		||||
      size: tcgsize; src1, src2, dst: tregister);
 | 
			
		||||
      var
 | 
			
		||||
        href : treference;
 | 
			
		||||
      begin
 | 
			
		||||
        if (op=OP_ADD) and (size in [OS_32,OS_S32,OS_64,OS_S64]) and
 | 
			
		||||
          not(cs_check_overflow in current_settings.localswitches) then
 | 
			
		||||
          begin
 | 
			
		||||
            reference_reset_base(href,src1,0,0);
 | 
			
		||||
            href.index:=src2;
 | 
			
		||||
            list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    procedure tcgx86.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
 | 
			
		||||
 | 
			
		||||
      var
 | 
			
		||||
        opcode : tasmop;
 | 
			
		||||
        power  : longint;
 | 
			
		||||
        href : treference;
 | 
			
		||||
{$ifdef x86_64}
 | 
			
		||||
        tmpreg : tregister;
 | 
			
		||||
{$endif x86_64}
 | 
			
		||||
@ -1605,6 +1668,7 @@ unit cgx86;
 | 
			
		||||
                  list.concat(taicpu.op_const_reg(A_SHL,TCgSize2OpSize[size],power,reg));
 | 
			
		||||
                  exit;
 | 
			
		||||
                end;
 | 
			
		||||
 | 
			
		||||
              if op = OP_IMUL then
 | 
			
		||||
                list.concat(taicpu.op_const_reg(A_IMUL,TCgSize2OpSize[size],a,reg))
 | 
			
		||||
              else
 | 
			
		||||
 | 
			
		||||
@ -85,6 +85,7 @@ unit nx86add;
 | 
			
		||||
        power : longint;
 | 
			
		||||
        hl4   : tasmlabel;
 | 
			
		||||
        r     : Tregister;
 | 
			
		||||
        href  : treference;
 | 
			
		||||
      begin
 | 
			
		||||
        { at this point, left.location.loc should be LOC_REGISTER }
 | 
			
		||||
        if right.location.loc=LOC_REGISTER then
 | 
			
		||||
@ -156,6 +157,18 @@ unit nx86add;
 | 
			
		||||
                  begin
 | 
			
		||||
                    emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
 | 
			
		||||
                  end
 | 
			
		||||
                else if (op=A_IMUL) and
 | 
			
		||||
                    (right.location.loc=LOC_CONSTANT) and
 | 
			
		||||
                    (right.location.value>1) and (ispowerof2(int64(right.location.value)-1,power)) and
 | 
			
		||||
                    (power in [1..3]) and
 | 
			
		||||
                    not(cs_check_overflow in current_settings.localswitches) then
 | 
			
		||||
                  begin
 | 
			
		||||
                    reference_reset_base(href,left.location.register,0,0);
 | 
			
		||||
                    href.index:=left.location.register;
 | 
			
		||||
                    href.scalefactor:=int64(right.location.value)-1;
 | 
			
		||||
                    left.location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
 | 
			
		||||
                    current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[opsize],href,left.location.register));
 | 
			
		||||
                  end
 | 
			
		||||
               else
 | 
			
		||||
                 begin
 | 
			
		||||
                   if extra_not then
 | 
			
		||||
@ -210,7 +223,7 @@ unit nx86add;
 | 
			
		||||
              { maybe we can reuse a constant register when the
 | 
			
		||||
                operation is a comparison that doesn't change the
 | 
			
		||||
                value of the register }
 | 
			
		||||
              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
 | 
			
		||||
                hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
 | 
			
		||||
            end;
 | 
			
		||||
          end;
 | 
			
		||||
        if (right.location.loc<>LOC_CONSTANT) and
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user