|
@@ -0,0 +1,144 @@
|
|
|
+{
|
|
|
+ Copyright (c) 2014 by Jonas Maebe
|
|
|
+
|
|
|
+ Generate AArch64 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 ncpucnv;
|
|
|
+
|
|
|
+{$i fpcdefs.inc}
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+ uses
|
|
|
+ node,ncnv,ncgcnv;
|
|
|
+
|
|
|
+ type
|
|
|
+ taarch64typeconvnode = class(TCgTypeConvNode)
|
|
|
+ protected
|
|
|
+ function typecheck_int_to_real: tnode; override;
|
|
|
+ function first_int_to_real: tnode; override;
|
|
|
+
|
|
|
+ { 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; }
|
|
|
+ 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,
|
|
|
+ symdef,aasmdata,
|
|
|
+ defutil,
|
|
|
+ cgbase,cgutils,
|
|
|
+ cpubase,aasmcpu,
|
|
|
+ cgobj,
|
|
|
+ hlcgobj;
|
|
|
+
|
|
|
+
|
|
|
+{*****************************************************************************
|
|
|
+ FirstTypeConv
|
|
|
+*****************************************************************************}
|
|
|
+
|
|
|
+ function taarch64typeconvnode.typecheck_int_to_real: tnode;
|
|
|
+ begin
|
|
|
+ { aarch64 supports converting everything to floating point, even fixed
|
|
|
+ point! Unfortunately, it only supports fixed point with a power-of-2
|
|
|
+ fraction, which is not the case for currency.
|
|
|
+
|
|
|
+ Generate the division by 10000 via nodes so the 10000.0 constant can
|
|
|
+ be reused. }
|
|
|
+ if is_currency(resultdef) and
|
|
|
+ not(nf_is_currency in flags) then
|
|
|
+ begin
|
|
|
+ { convert the equivalent int64 value to double without conversion
|
|
|
+ (internal typecast -> will set nf_is_currency flag) }
|
|
|
+ result:=ctypeconvnode.create_internal(left,s64floattype);
|
|
|
+ { turn into currency with conversion, which will divide by 10000
|
|
|
+ (regular typecast) }
|
|
|
+ result:=ctypeconvnode.create(result,s64currencytype);
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ { The only other thing we have to take care of: convert values < 32 bit
|
|
|
+ to 32 bit }
|
|
|
+ if left.resultdef.size<4 then
|
|
|
+ begin
|
|
|
+ if is_signed(left.resultdef) then
|
|
|
+ inserttypeconv(left,s32inttype)
|
|
|
+ else
|
|
|
+ inserttypeconv(left,u32inttype)
|
|
|
+ end;
|
|
|
+ result:=inherited;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ function taarch64typeconvnode.first_int_to_real: tnode;
|
|
|
+ begin
|
|
|
+ result:=nil;
|
|
|
+ expectloc:=LOC_MMREGISTER;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{*****************************************************************************
|
|
|
+ SecondTypeConv
|
|
|
+*****************************************************************************}
|
|
|
+
|
|
|
+ procedure taarch64typeconvnode.second_int_to_real;
|
|
|
+ var
|
|
|
+ op: tasmop;
|
|
|
+ begin
|
|
|
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
|
|
|
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
|
|
|
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
|
|
|
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
|
|
+ internalerror(2014120401);
|
|
|
+ case left.location.size of
|
|
|
+ OS_32,
|
|
|
+ OS_64:
|
|
|
+ op:=A_UCVTF;
|
|
|
+ OS_S32,
|
|
|
+ OS_S64,
|
|
|
+ { for currency and comp }
|
|
|
+ OS_F64:
|
|
|
+ op:=A_SCVTF;
|
|
|
+ else
|
|
|
+ internalerror(2014120402);
|
|
|
+ end;
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
|
|
|
+ { no scaling for currency, that's handled in pass_typecheck }
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+begin
|
|
|
+ ctypeconvnode:=taarch64typeconvnode;
|
|
|
+end.
|