mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 12:59:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			149 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2002 by Florian Klaempfl
 | 
						|
 | 
						|
    Generate i386 inline nodes
 | 
						|
 | 
						|
    This program is free software; you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU General Public License as published by
 | 
						|
    the Free Software Foundation; either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with this program; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
unit n386inl;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
       node,nx86inl;
 | 
						|
 | 
						|
    type
 | 
						|
       ti386inlinenode = class(tx86inlinenode)
 | 
						|
       public
 | 
						|
         function first_sar: tnode; override;
 | 
						|
         procedure second_rox_sar; override;
 | 
						|
         procedure second_abs_long; override;
 | 
						|
       end;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
  uses
 | 
						|
    globtype,globals,compinnr,
 | 
						|
    defutil,
 | 
						|
    aasmbase,aasmdata,
 | 
						|
    cgbase,pass_2,
 | 
						|
    cpuinfo,cpubase,
 | 
						|
    cga,cgutils,cgx86,cgobj,hlcgobj,
 | 
						|
    ninl,ncon,ncal;
 | 
						|
 | 
						|
 | 
						|
  function ti386inlinenode.first_sar: tnode;
 | 
						|
    begin
 | 
						|
      if is_64bitint(resultdef) and (
 | 
						|
        (inlinenumber=in_sar_x) or (
 | 
						|
          (inlinenumber=in_sar_x_y) and
 | 
						|
          (tcallparanode(left).left.nodetype=ordconstn)
 | 
						|
      )) then
 | 
						|
        begin
 | 
						|
          result:=nil;
 | 
						|
          expectloc:=LOC_REGISTER;
 | 
						|
        end
 | 
						|
      else
 | 
						|
        result:=inherited first_sar;
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
  procedure ti386inlinenode.second_rox_sar;
 | 
						|
    var
 | 
						|
      op1: tnode;
 | 
						|
      hreg64hi,hreg64lo: tregister;
 | 
						|
      v: aint;
 | 
						|
    begin
 | 
						|
      if is_64bitint(resultdef) and (
 | 
						|
        (inlinenumber=in_sar_x) or (
 | 
						|
          (inlinenumber=in_sar_x_y) and
 | 
						|
          (tcallparanode(left).left.nodetype=ordconstn)
 | 
						|
      )) then
 | 
						|
        begin
 | 
						|
          { x sar constant }
 | 
						|
          if (left.nodetype=callparan) and
 | 
						|
             assigned(tcallparanode(left).right) then
 | 
						|
            begin
 | 
						|
              op1:=tcallparanode(tcallparanode(left).right).left;
 | 
						|
              secondpass(tcallparanode(left).left);
 | 
						|
              v:=Tordconstnode(tcallparanode(left).left).value.svalue and 63;
 | 
						|
            end
 | 
						|
          else
 | 
						|
            begin
 | 
						|
              op1:=left;
 | 
						|
              v:=1;
 | 
						|
            end;
 | 
						|
          secondpass(op1);
 | 
						|
 | 
						|
          location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
 | 
						|
 | 
						|
          { load left operator in a register }
 | 
						|
          hlcg.location_force_reg(current_asmdata.CurrAsmList,op1.location,op1.resultdef,resultdef,false);
 | 
						|
          hreg64hi:=op1.location.register64.reghi;
 | 
						|
          hreg64lo:=op1.location.register64.reglo;
 | 
						|
 | 
						|
          if (v=63) then
 | 
						|
            begin
 | 
						|
              emit_const_reg(A_SAR,S_L,31,hreg64hi);
 | 
						|
              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,hreg64hi,hreg64lo);
 | 
						|
            end
 | 
						|
          else if (v>31) then
 | 
						|
            begin
 | 
						|
              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,hreg64hi,hreg64lo);
 | 
						|
              emit_const_reg(A_SAR,S_L,31,hreg64hi);
 | 
						|
              emit_const_reg(A_SAR,S_L,v and 31,hreg64lo);
 | 
						|
            end
 | 
						|
          else
 | 
						|
            begin
 | 
						|
              emit_const_reg_reg(A_SHRD,S_L,v and 31,hreg64hi,hreg64lo);
 | 
						|
              emit_const_reg(A_SAR,S_L,v and 31,hreg64hi);
 | 
						|
            end;
 | 
						|
          location.register64.reghi:=hreg64hi;
 | 
						|
          location.register64.reglo:=hreg64lo;
 | 
						|
        end
 | 
						|
      else
 | 
						|
        inherited second_rox_sar;
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
  procedure ti386inlinenode.second_abs_long;
 | 
						|
    begin
 | 
						|
      if is_64bitint(left.resultdef) then
 | 
						|
        begin
 | 
						|
          secondpass(left);
 | 
						|
          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
 | 
						|
          location:=left.location;
 | 
						|
          location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
 | 
						|
          location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
 | 
						|
          cg64.a_load64_reg_reg(current_asmdata.CurrAsmList,left.location.register64,location.register64);
 | 
						|
          cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_32,31,left.location.register64.reghi);
 | 
						|
          cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,left.location.register64.reghi,location.register64.reglo);
 | 
						|
          cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,left.location.register64.reghi,location.register64.reghi);
 | 
						|
          emit_reg_reg(A_SUB,S_L,left.location.register64.reghi,location.register64.reglo);
 | 
						|
          emit_reg_reg(A_SBB,S_L,left.location.register64.reghi,location.register64.reghi);
 | 
						|
        end
 | 
						|
      else
 | 
						|
        inherited second_abs_long;
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
begin
 | 
						|
   cinlinenode:=ti386inlinenode;
 | 
						|
end.
 |