narmutil.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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_armv3:
  87. begin
  88. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,0));
  89. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  90. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,''));
  91. end;
  92. cpu_armv4:
  93. begin
  94. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,1));
  95. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  96. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'4'));
  97. end;
  98. cpu_armv4t:
  99. begin
  100. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,2));
  101. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  102. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'4T'));
  103. end;
  104. cpu_armv5t:
  105. begin
  106. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,3));
  107. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  108. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'5T'));
  109. end;
  110. cpu_armv5te:
  111. begin
  112. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,4));
  113. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  114. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'5TE'));
  115. end;
  116. cpu_armv5tej:
  117. begin
  118. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,5));
  119. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  120. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'5TEJ'));
  121. end;
  122. cpu_armv6:
  123. begin
  124. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,6));
  125. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  126. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6'));
  127. end;
  128. cpu_armv6k:
  129. begin
  130. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,9));
  131. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  132. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6K'));
  133. end;
  134. cpu_armv6t2:
  135. begin
  136. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,8));
  137. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  138. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'T2'));
  139. end;
  140. cpu_armv6z:
  141. begin
  142. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,7));
  143. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  144. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6Z'));
  145. end;
  146. cpu_armv6m:
  147. begin
  148. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,11));
  149. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  150. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'6-M'));
  151. end;
  152. cpu_armv7:
  153. begin
  154. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  155. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,0));
  156. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7'));
  157. end;
  158. cpu_armv7a:
  159. begin
  160. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  161. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$41));
  162. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7-A'));
  163. end;
  164. cpu_armv7r:
  165. begin
  166. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  167. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$52));
  168. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7-R'));
  169. end;
  170. cpu_armv7m:
  171. begin
  172. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,10));
  173. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$4D));
  174. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7-M'));
  175. end;
  176. cpu_armv7em:
  177. begin
  178. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch,13));
  179. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_arch_profile,$4D));
  180. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_CPU_name,'7E-M'));
  181. end;
  182. else
  183. Internalerror(2019100602);
  184. end;
  185. case current_settings.fputype of
  186. fpu_none,
  187. fpu_soft,
  188. fpu_libgcc,
  189. fpu_fpa,
  190. fpu_fpa10,
  191. fpu_fpa11:
  192. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,0));
  193. fpu_vfpv2:
  194. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,2));
  195. fpu_vfpv3,
  196. fpu_neon_vfpv3:
  197. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,3));
  198. fpu_vfpv3_d16:
  199. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,4));
  200. fpu_fpv4_sp_d16,
  201. fpu_fpv4_s16:
  202. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,6));
  203. fpu_vfpv4,
  204. fpu_neon_vfpv4:
  205. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,5));
  206. { else not needed anymore PM 2020/04/13
  207. Internalerror(2019100603); }
  208. end;
  209. if FPUARM_HAS_FMA in fpu_capabilities[current_settings.fputype] then
  210. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,2))
  211. else if FPUARM_HAS_NEON in fpu_capabilities[current_settings.fputype] then
  212. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,1))
  213. else
  214. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,0));
  215. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ARM_ISA_use,1));
  216. if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then
  217. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_THUMB_ISA_use,2))
  218. else
  219. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_THUMB_ISA_use,1));
  220. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_VFP_args,1));
  221. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_denormal,1));
  222. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_exceptions,1));
  223. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_number_model,3));
  224. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_align_needed,0));
  225. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_align8_preserved,1));
  226. { gcc typically writes more like enum size, wchar size, optimization goal, however, this
  227. is normally not module global in FPC }
  228. end;
  229. end;
  230. class procedure tarmnodeutils.insert_init_final_table(entries:tfplist);
  231. procedure genentry(list : TAsmList);
  232. var
  233. ref: treference;
  234. begin
  235. if GenerateThumbCode then
  236. list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R14]))
  237. else
  238. begin
  239. reference_reset(ref,4,[]);
  240. ref.index:=NR_STACK_POINTER_REG;
  241. ref.addressmode:=AM_PREINDEXED;
  242. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R14]),PF_FD));
  243. end;
  244. end;
  245. procedure genexit(list : TAsmList);
  246. var
  247. ref: treference;
  248. begin
  249. if GenerateThumbCode then
  250. list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R15]))
  251. else
  252. begin
  253. reference_reset(ref,4,[]);
  254. ref.index:=NR_STACK_POINTER_REG;
  255. ref.addressmode:=AM_PREINDEXED;
  256. list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R15]),PF_FD));
  257. end;
  258. end;
  259. var
  260. initList, finalList, header: TAsmList;
  261. entry : pinitfinalentry;
  262. i : longint;
  263. begin
  264. if not(tf_init_final_units_by_calls in target_info.flags) then
  265. begin
  266. inherited insert_init_final_table(entries);
  267. exit;
  268. end;
  269. initList:=TAsmList.create;
  270. finalList:=TAsmList.create;
  271. genentry(finalList);
  272. genentry(initList);
  273. for i:=0 to entries.count-1 do
  274. begin
  275. entry:=pinitfinalentry(entries[i]);
  276. if entry^.finifunc<>'' then
  277. finalList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.finifunc,AT_FUNCTION)));
  278. if entry^.initfunc<>'' then
  279. initList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.initfunc,AT_FUNCTION)));
  280. end;
  281. genexit(finalList);
  282. genexit(initList);
  283. header:=TAsmList.create;
  284. new_section(header, sec_code, 'FPC_INIT_FUNC_TABLE', 1);
  285. header.concat(tai_symbol.Createname_global('FPC_INIT_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
  286. initList.insertList(header);
  287. header.free;
  288. current_asmdata.AsmLists[al_procedures].concatList(initList);
  289. header:=TAsmList.create;
  290. new_section(header, sec_code, 'FPC_FINALIZE_FUNC_TABLE', 1);
  291. header.concat(tai_symbol.Createname_global('FPC_FINALIZE_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
  292. finalList.insertList(header);
  293. header.free;
  294. current_asmdata.AsmLists[al_procedures].concatList(finalList);
  295. initList.Free;
  296. finalList.Free;
  297. inherited insert_init_final_table(entries);
  298. end;
  299. begin
  300. cnodeutils:=tarmnodeutils;
  301. end.