narmutil.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. {
  2. Copyright (c) 2019 by Florian Klämpfl
  3. ARM version of some node tree helper routines
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit narmutil;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,ngenutil;
  22. type
  23. tarmnodeutils = class(tnodeutils)
  24. class procedure InsertObjectInfo; override;
  25. class procedure insert_init_final_table(entries: tfplist); override;
  26. end;
  27. implementation
  28. uses
  29. verbose,
  30. systems,
  31. globals,
  32. cpuinfo,cpubase,
  33. cgbase,cgutils,
  34. aasmbase,aasmdata,aasmtai,aasmcpu,
  35. symdef;
  36. const
  37. Tag_File = 1;
  38. Tag_Section = 2;
  39. Tag_Symbol = 3;
  40. Tag_CPU_raw_name = 4;
  41. Tag_CPU_name = 5;
  42. Tag_CPU_arch = 6;
  43. Tag_CPU_arch_profile = 7;
  44. Tag_ARM_ISA_use = 8;
  45. Tag_THUMB_ISA_use = 9;
  46. Tag_FP_Arch = 10;
  47. Tag_WMMX_arch = 11;
  48. Tag_Advanced_SIMD_arch = 12;
  49. Tag_PCS_config = 13;
  50. Tag_ABI_PCS_R9_use = 14;
  51. Tag_ABI_PCS_RW_data = 15;
  52. Tag_ABI_PCS_RO_data = 16;
  53. Tag_ABI_PCS_GOT_use = 17;
  54. Tag_ABI_PCS_wchar_t = 18;
  55. Tag_ABI_FP_rounding = 19;
  56. Tag_ABI_FP_denormal = 20;
  57. Tag_ABI_FP_exceptions = 21;
  58. Tag_ABI_FP_user_exceptions = 22;
  59. Tag_ABI_FP_number_model = 23;
  60. Tag_ABI_align_needed = 24;
  61. Tag_ABI_align8_preserved = 25;
  62. Tag_ABI_enum_size = 26;
  63. Tag_ABI_HardFP_use = 27;
  64. Tag_ABI_VFP_args = 28;
  65. Tag_ABI_WMMX_args = 29;
  66. Tag_ABI_optimization_goals = 30;
  67. Tag_ABI_FP_optimization_goals = 31;
  68. Tag_compatiblity = 32;
  69. Tag_CPU_unaligned_access = 34;
  70. Tag_FP_HP_extension = 36;
  71. Tag_ABI_FP_16bit_format = 38;
  72. Tag_MPextension_use = 42;
  73. Tag_DIV_use = 44;
  74. Tag_nodefaults = 64;
  75. Tag_also_compatible_with = 65;
  76. Tag_conformance = 67;
  77. Tag_T2EE_use = 66;
  78. Tag_Virtualization_use = 68;
  79. class procedure tarmnodeutils.InsertObjectInfo;
  80. begin
  81. inherited InsertObjectInfo;
  82. { write eabi attributes to object file? }
  83. if (target_info.system in [system_arm_linux]) and (target_info.abi in [abi_eabihf,abi_eabi]) then
  84. begin
  85. case current_settings.cputype of
  86. cpu_armv2,
  87. cpu_armv3:
  88. begin
  89. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,0));
  90. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  91. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,''));
  92. end;
  93. cpu_armv4:
  94. begin
  95. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,1));
  96. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  97. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'4'));
  98. end;
  99. cpu_armv4t:
  100. begin
  101. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,2));
  102. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  103. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'4T'));
  104. end;
  105. cpu_armv5t:
  106. begin
  107. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,3));
  108. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  109. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'5T'));
  110. end;
  111. cpu_armv5te:
  112. begin
  113. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,4));
  114. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  115. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'5TE'));
  116. end;
  117. cpu_armv5tej:
  118. begin
  119. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,5));
  120. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  121. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'5TEJ'));
  122. end;
  123. cpu_armv6:
  124. begin
  125. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,6));
  126. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  127. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6'));
  128. end;
  129. cpu_armv6k:
  130. begin
  131. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,9));
  132. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  133. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6K'));
  134. end;
  135. cpu_armv6t2:
  136. begin
  137. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,8));
  138. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  139. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'T2'));
  140. end;
  141. cpu_armv6z:
  142. begin
  143. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,7));
  144. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  145. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6Z'));
  146. end;
  147. cpu_armv6m:
  148. begin
  149. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,11));
  150. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  151. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6-M'));
  152. end;
  153. cpu_armv7:
  154. begin
  155. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  156. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  157. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7'));
  158. end;
  159. cpu_armv7a:
  160. begin
  161. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  162. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$41));
  163. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7-A'));
  164. end;
  165. cpu_armv7r:
  166. begin
  167. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  168. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$52));
  169. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7-R'));
  170. end;
  171. cpu_armv7m:
  172. begin
  173. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  174. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$4D));
  175. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7-M'));
  176. end;
  177. cpu_armv7em:
  178. begin
  179. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,13));
  180. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$4D));
  181. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7E-M'));
  182. end;
  183. else
  184. Internalerror(2019100602);
  185. end;
  186. case current_settings.fputype of
  187. fpu_none,
  188. fpu_soft,
  189. fpu_libgcc,
  190. fpu_fpa,
  191. fpu_fpa10,
  192. fpu_fpa11:
  193. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,0));
  194. fpu_vfpv2:
  195. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,2));
  196. fpu_vfpv3,
  197. fpu_neon_vfpv3:
  198. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,3));
  199. fpu_vfpv3_d16:
  200. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,4));
  201. fpu_fpv4_sp_d16,
  202. fpu_fpv4_s16:
  203. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,6));
  204. fpu_vfpv4,
  205. fpu_neon_vfpv4:
  206. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,5));
  207. fpu_fpv5_sp_d16,
  208. fpu_fpv5_d16:
  209. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,8));
  210. fpu_fp_armv8:
  211. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,7));
  212. { else not needed anymore PM 2020/04/13
  213. Internalerror(2019100603); }
  214. end;
  215. if FPUARM_HAS_FMA in fpu_capabilities[current_settings.fputype] then
  216. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,2))
  217. else if FPUARM_HAS_NEON in fpu_capabilities[current_settings.fputype] then
  218. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,1))
  219. else
  220. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,0));
  221. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ARM_ISA_use,1));
  222. if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then
  223. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_THUMB_ISA_use,2))
  224. else
  225. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_THUMB_ISA_use,1));
  226. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_VFP_args,1));
  227. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_denormal,1));
  228. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_exceptions,1));
  229. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_number_model,3));
  230. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_align_needed,0));
  231. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_align8_preserved,1));
  232. { gcc typically writes more like enum size, wchar size, optimization goal, however, this
  233. is normally not module global in FPC }
  234. end;
  235. end;
  236. class procedure tarmnodeutils.insert_init_final_table(entries:tfplist);
  237. procedure genentry(list : TAsmList);
  238. var
  239. ref: treference;
  240. begin
  241. if GenerateThumbCode then
  242. list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R14]))
  243. else
  244. begin
  245. reference_reset(ref,4,[]);
  246. ref.index:=NR_STACK_POINTER_REG;
  247. ref.addressmode:=AM_PREINDEXED;
  248. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R14]),PF_FD));
  249. end;
  250. end;
  251. procedure genexit(list : TAsmList);
  252. var
  253. ref: treference;
  254. begin
  255. if GenerateThumbCode then
  256. list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R15]))
  257. else
  258. begin
  259. reference_reset(ref,4,[]);
  260. ref.index:=NR_STACK_POINTER_REG;
  261. ref.addressmode:=AM_PREINDEXED;
  262. list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R15]),PF_FD));
  263. end;
  264. end;
  265. var
  266. initList, finalList, header: TAsmList;
  267. entry : pinitfinalentry;
  268. i : longint;
  269. begin
  270. if not(tf_init_final_units_by_calls in target_info.flags) then
  271. begin
  272. inherited insert_init_final_table(entries);
  273. exit;
  274. end;
  275. initList:=TAsmList.create;
  276. finalList:=TAsmList.create;
  277. genentry(finalList);
  278. genentry(initList);
  279. for i:=0 to entries.count-1 do
  280. begin
  281. entry:=pinitfinalentry(entries[i]);
  282. if entry^.finifunc<>'' then
  283. finalList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.finifunc,AT_FUNCTION)));
  284. if entry^.initfunc<>'' then
  285. initList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.initfunc,AT_FUNCTION)));
  286. end;
  287. genexit(finalList);
  288. genexit(initList);
  289. header:=TAsmList.create;
  290. new_section(header, sec_code, 'FPC_INIT_FUNC_TABLE', 1);
  291. header.concat(tai_symbol.Createname_global('FPC_INIT_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
  292. initList.insertList(header);
  293. header.free;
  294. current_asmdata.AsmLists[al_procedures].concatList(initList);
  295. header:=TAsmList.create;
  296. new_section(header, sec_code, 'FPC_FINALIZE_FUNC_TABLE', 1);
  297. header.concat(tai_symbol.Createname_global('FPC_FINALIZE_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
  298. finalList.insertList(header);
  299. header.free;
  300. current_asmdata.AsmLists[al_procedures].concatList(finalList);
  301. initList.Free;
  302. finalList.Free;
  303. inherited insert_init_final_table(entries);
  304. end;
  305. begin
  306. cnodeutils:=tarmnodeutils;
  307. end.