{ Copyright (c) 2019 by Florian Klämpfl ARM version of some node tree helper routines 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 narmutil; {$i fpcdefs.inc} interface uses cclasses,ngenutil,fmodule; type tarmnodeutils = class(tnodeutils) class procedure InsertObjectInfo; override; class procedure insert_init_final_table(main : tmodule; entries: tfplist); override; end; implementation uses verbose, systems, globals, cpuinfo,cpubase, cgbase,cgutils, aasmbase,aasmdata,aasmtai,aasmcpu, symdef; const Tag_File = 1; Tag_Section = 2; Tag_Symbol = 3; Tag_CPU_raw_name = 4; Tag_CPU_name = 5; Tag_CPU_arch = 6; Tag_CPU_arch_profile = 7; Tag_ARM_ISA_use = 8; Tag_THUMB_ISA_use = 9; Tag_FP_Arch = 10; Tag_WMMX_arch = 11; Tag_Advanced_SIMD_arch = 12; Tag_PCS_config = 13; Tag_ABI_PCS_R9_use = 14; Tag_ABI_PCS_RW_data = 15; Tag_ABI_PCS_RO_data = 16; Tag_ABI_PCS_GOT_use = 17; Tag_ABI_PCS_wchar_t = 18; Tag_ABI_FP_rounding = 19; Tag_ABI_FP_denormal = 20; Tag_ABI_FP_exceptions = 21; Tag_ABI_FP_user_exceptions = 22; Tag_ABI_FP_number_model = 23; Tag_ABI_align_needed = 24; Tag_ABI_align8_preserved = 25; Tag_ABI_enum_size = 26; Tag_ABI_HardFP_use = 27; Tag_ABI_VFP_args = 28; Tag_ABI_WMMX_args = 29; Tag_ABI_optimization_goals = 30; Tag_ABI_FP_optimization_goals = 31; Tag_compatiblity = 32; Tag_CPU_unaligned_access = 34; Tag_FP_HP_extension = 36; Tag_ABI_FP_16bit_format = 38; Tag_MPextension_use = 42; Tag_DIV_use = 44; Tag_nodefaults = 64; Tag_also_compatible_with = 65; Tag_conformance = 67; Tag_T2EE_use = 66; Tag_Virtualization_use = 68; class procedure tarmnodeutils.InsertObjectInfo; begin inherited InsertObjectInfo; { write eabi attributes to object file? } if (target_info.system in [system_arm_linux]) and (target_info.abi in [abi_eabihf,abi_eabi]) then begin case current_settings.cputype of cpu_armv2, cpu_armv3: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'')); end; cpu_armv4: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,1)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'4')); end; cpu_armv4t: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,2)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'4T')); end; cpu_armv5t: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,3)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'5T')); end; cpu_armv5te: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,4)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'5TE')); end; cpu_armv5tej: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,5)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'5TEJ')); end; cpu_armv6: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,6)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'6')); end; cpu_armv6k: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,9)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'6K')); end; cpu_armv6t2: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,8)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'T2')); end; cpu_armv6z: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,7)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'6Z')); end; cpu_armv6m: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,11)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'6-M')); end; cpu_armv7: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,10)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'7')); end; cpu_armv7a: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,10)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,$41)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'7-A')); end; cpu_armv7r: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,10)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,$52)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'7-R')); end; cpu_armv7m: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,10)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,$4D)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'7-M')); end; cpu_armv7em: begin current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch,13)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_arch_profile,$4D)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_CPU_name,'7E-M')); end; else Internalerror(2019100602); end; case current_settings.fputype of fpu_none, fpu_soft, fpu_libgcc, fpu_fpa, fpu_fpa10, fpu_fpa11: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,0)); fpu_vfpv2: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,2)); fpu_vfpv3, fpu_neon_vfpv3: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,3)); fpu_vfpv3_d16: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,4)); fpu_fpv4_sp_d16, fpu_fpv4_s16: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,6)); fpu_vfpv4, fpu_neon_vfpv4: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,5)); fpu_fpv5_sp_d16, fpu_fpv5_d16: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,8)); fpu_fp_armv8: current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_FP_Arch,7)); { else not needed anymore PM 2020/04/13 Internalerror(2019100603); } end; if FPUARM_HAS_FMA in fpu_capabilities[current_settings.fputype] then current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_Advanced_SIMD_arch,2)) else if FPUARM_HAS_NEON in fpu_capabilities[current_settings.fputype] then current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_Advanced_SIMD_arch,1)) else current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_Advanced_SIMD_arch,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ARM_ISA_use,1)); if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_THUMB_ISA_use,2)) else current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_THUMB_ISA_use,1)); if target_info.abi=abi_eabihf then current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_VFP_args,1)) else current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_VFP_args,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_FP_denormal,1)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_FP_exceptions,1)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_FP_number_model,3)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_align_needed,0)); current_asmdata.asmlists[al_start].Concat(tai_attribute.create(ait_eabi_attribute,Tag_ABI_align8_preserved,1)); { gcc typically writes more like enum size, wchar size, optimization goal, however, this is normally not module global in FPC } end; end; class procedure tarmnodeutils.insert_init_final_table(main : tmodule; entries:tfplist); procedure genentry(list : TAsmList); var ref: treference; begin if GenerateThumbCode then list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R14])) else begin reference_reset(ref,4,[]); ref.index:=NR_STACK_POINTER_REG; ref.addressmode:=AM_PREINDEXED; list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R14]),PF_FD)); end; end; procedure genexit(list : TAsmList); var ref: treference; begin if GenerateThumbCode then list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R15])) else begin reference_reset(ref,4,[]); ref.index:=NR_STACK_POINTER_REG; ref.addressmode:=AM_PREINDEXED; list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R15]),PF_FD)); end; end; var initList, finalList, header: TAsmList; entry : pinitfinalentry; i : longint; begin if not(tf_init_final_units_by_calls in target_info.flags) then begin inherited insert_init_final_table(main,entries); exit; end; initList:=TAsmList.create; finalList:=TAsmList.create; genentry(finalList); genentry(initList); for i:=0 to entries.count-1 do begin entry:=pinitfinalentry(entries[i]); if entry^.finifunc<>'' then finalList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.finifunc,AT_FUNCTION))); if entry^.initfunc<>'' then initList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.initfunc,AT_FUNCTION))); end; genexit(finalList); genexit(initList); header:=TAsmList.create; new_section(header, sec_code, 'FPC_INIT_FUNC_TABLE', 1); header.concat(tai_symbol.Createname_global('FPC_INIT_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype)); initList.insertList(header); header.free; current_asmdata.AsmLists[al_procedures].concatList(initList); header:=TAsmList.create; new_section(header, sec_code, 'FPC_FINALIZE_FUNC_TABLE', 1); header.concat(tai_symbol.Createname_global('FPC_FINALIZE_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype)); finalList.insertList(header); header.free; current_asmdata.AsmLists[al_procedures].concatList(finalList); initList.Free; finalList.Free; inherited insert_init_final_table(main,entries); end; begin cnodeutils:=tarmnodeutils; end.