mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 04:59:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			176 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2002 by Florian Klaempfl
 | 
						|
 | 
						|
    Generate x86-64 assembler for type converting 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 nx64cnv;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
      node,ncgcnv,defutil,defcmp,pass_1,
 | 
						|
      nx86cnv;
 | 
						|
 | 
						|
    type
 | 
						|
       tx8664typeconvnode = class(tx86typeconvnode)
 | 
						|
         protected
 | 
						|
         { procedure second_int_to_int;override; }
 | 
						|
         { procedure second_string_to_string;override; }
 | 
						|
         { procedure second_cstring_to_pchar;override; }
 | 
						|
         { procedure second_string_to_chararray;override; }
 | 
						|
         { procedure second_array_to_pointer;override; }
 | 
						|
         { procedure second_pointer_to_array;override; }
 | 
						|
         { procedure second_chararray_to_string;override; }
 | 
						|
         { procedure second_char_to_string;override; }
 | 
						|
         { function first_int_to_real: tnode; override; }
 | 
						|
         function first_int_to_real : tnode;override;
 | 
						|
         procedure second_int_to_real;override;
 | 
						|
         { procedure second_real_to_real;override; }
 | 
						|
         { procedure second_cord_to_pointer;override; }
 | 
						|
         { procedure second_proc_to_procvar;override; }
 | 
						|
         { procedure second_bool_to_int;override; }
 | 
						|
         { procedure second_int_to_bool;override; }
 | 
						|
         { procedure second_load_smallset;override;  }
 | 
						|
         { procedure second_ansistring_to_pchar;override; }
 | 
						|
         { procedure second_pchar_to_string;override; }
 | 
						|
         { procedure second_class_to_intf;override;  }
 | 
						|
         { procedure second_char_to_char;override; }
 | 
						|
       end;
 | 
						|
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      verbose,systems,globals,globtype,
 | 
						|
      aasmbase,aasmtai,aasmdata,aasmcpu,
 | 
						|
      symconst,symdef,
 | 
						|
      cgbase,cga,procinfo,pass_2,
 | 
						|
      ncon,ncal,ncnv,
 | 
						|
      cpubase,
 | 
						|
      cgutils,cgobj,cgx86,ncgutil,
 | 
						|
      tgobj;
 | 
						|
 | 
						|
 | 
						|
    function tx8664typeconvnode.first_int_to_real : tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        if use_vectorfpu(resultdef) and
 | 
						|
           (torddef(left.resultdef).ordtype=u32bit) then
 | 
						|
          begin
 | 
						|
            inserttypeconv(left,s64inttype);
 | 
						|
            firstpass(left);
 | 
						|
          end
 | 
						|
        else
 | 
						|
          result:=inherited first_int_to_real;
 | 
						|
       if use_vectorfpu(resultdef) then
 | 
						|
         expectloc:=LOC_MMREGISTER;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tx8664typeconvnode.second_int_to_real;
 | 
						|
      var
 | 
						|
         href : treference;
 | 
						|
         l1,l2 : tasmlabel;
 | 
						|
         op : tasmop;
 | 
						|
      begin
 | 
						|
        if use_vectorfpu(resultdef) then
 | 
						|
          begin
 | 
						|
            if is_double(resultdef) then
 | 
						|
              op:=A_CVTSI2SD
 | 
						|
            else if is_single(resultdef) then
 | 
						|
              op:=A_CVTSI2SS
 | 
						|
            else
 | 
						|
              internalerror(200506061);
 | 
						|
 | 
						|
            location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
 | 
						|
            location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
 | 
						|
 | 
						|
            case torddef(left.resultdef).ordtype of
 | 
						|
              u64bit:
 | 
						|
                begin
 | 
						|
                   { unsigned 64 bit ints are harder to handle:
 | 
						|
                     we load bits 0..62 and then check bit 63:
 | 
						|
                     if it is 1 then we add $80000000 000000000
 | 
						|
                     as double                                  }
 | 
						|
                   current_asmdata.getdatalabel(l1);
 | 
						|
                   current_asmdata.getjumplabel(l2);
 | 
						|
 | 
						|
                   { Get sign bit }
 | 
						|
                   if not(left.location.loc in [LOC_REGISTER,LOC_REFERENCE]) then
 | 
						|
                     location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,false);
 | 
						|
                   case left.location.loc of
 | 
						|
                     LOC_REGISTER :
 | 
						|
                       begin
 | 
						|
                         emit_const_reg(A_BT,S_Q,63,left.location.register);
 | 
						|
                         current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_Q,left.location.register,location.register));
 | 
						|
                       end;
 | 
						|
                     LOC_REFERENCE :
 | 
						|
                       begin
 | 
						|
                         href:=left.location.reference;
 | 
						|
                         tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
 | 
						|
                         inc(href.offset,4);
 | 
						|
                         emit_const_ref(A_BT,S_L,31,href);
 | 
						|
                         dec(href.offset,4);
 | 
						|
                         current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,S_Q,href,location.register));
 | 
						|
                       end;
 | 
						|
                     else
 | 
						|
                       internalerror(200710181);
 | 
						|
                   end;
 | 
						|
 | 
						|
                   cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NC,l2);
 | 
						|
                   new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(sizeof(pint)));
 | 
						|
                   current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
 | 
						|
                   reference_reset_symbol(href,l1,0,4);
 | 
						|
                   { simplify for PIC }
 | 
						|
                   tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
 | 
						|
 | 
						|
                   { I got these constant from a test program (FK) }
 | 
						|
                   if is_double(resultdef) then
 | 
						|
                     begin
 | 
						|
                       { double (2^64) }
 | 
						|
                       current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
 | 
						|
                       current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($43f00000));
 | 
						|
                       tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
 | 
						|
                       current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ADDSD,S_NO,href,location.register));
 | 
						|
                     end
 | 
						|
                   else if is_single(resultdef) then
 | 
						|
                     begin
 | 
						|
                       { single(2^64) }
 | 
						|
                       current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($5f800000));
 | 
						|
                       current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ADDSS,S_NO,href,location.register));
 | 
						|
                     end
 | 
						|
                   else
 | 
						|
                     internalerror(200506071);
 | 
						|
                   cg.a_label(current_asmdata.CurrAsmList,l2);
 | 
						|
                end
 | 
						|
              else
 | 
						|
                inherited second_int_to_real;
 | 
						|
            end;
 | 
						|
          end
 | 
						|
        else
 | 
						|
          inherited second_int_to_real;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
begin
 | 
						|
   ctypeconvnode:=tx8664typeconvnode;
 | 
						|
end.
 |