narmutil.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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_soft,
  187. fpu_libgcc:
  188. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,0));
  189. fpu_vfpv2:
  190. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,2));
  191. fpu_vfpv3,
  192. fpu_neon_vfpv3:
  193. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,3));
  194. fpu_vfpv3_d16:
  195. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,4));
  196. fpu_fpv4_sp_d16,
  197. fpu_fpv4_s16:
  198. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,6));
  199. fpu_vfpv4,
  200. fpu_neon_vfpv4:
  201. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,5));
  202. else
  203. Internalerror(2019100603);
  204. end;
  205. if FPUARM_HAS_FMA in fpu_capabilities[current_settings.fputype] then
  206. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,2))
  207. else if FPUARM_HAS_NEON in fpu_capabilities[current_settings.fputype] then
  208. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,1))
  209. else
  210. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,0));
  211. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ARM_ISA_use,1));
  212. if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then
  213. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_THUMB_ISA_use,2))
  214. else
  215. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_THUMB_ISA_use,1));
  216. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_VFP_args,1));
  217. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_denormal,1));
  218. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_exceptions,1));
  219. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_FP_number_model,3));
  220. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_align_needed,0));
  221. current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_ABI_align8_preserved,1));
  222. { gcc typically writes more like enum size, wchar size, optimization goal, however, this
  223. is normally not module global in FPC }
  224. end;
  225. end;
  226. class procedure tarmnodeutils.insert_init_final_table(entries:tfplist);
  227. procedure genentry(list : TAsmList);
  228. var
  229. ref: treference;
  230. begin
  231. if GenerateThumbCode then
  232. list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R14]))
  233. else
  234. begin
  235. reference_reset(ref,4,[]);
  236. ref.index:=NR_STACK_POINTER_REG;
  237. ref.addressmode:=AM_PREINDEXED;
  238. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R14]),PF_FD));
  239. end;
  240. end;
  241. procedure genexit(list : TAsmList);
  242. var
  243. ref: treference;
  244. begin
  245. if GenerateThumbCode then
  246. list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R15]))
  247. else
  248. begin
  249. reference_reset(ref,4,[]);
  250. ref.index:=NR_STACK_POINTER_REG;
  251. ref.addressmode:=AM_PREINDEXED;
  252. list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,[RS_R15]),PF_FD));
  253. end;
  254. end;
  255. var
  256. initList, finalList, header: TAsmList;
  257. entry : pinitfinalentry;
  258. i : longint;
  259. begin
  260. if not(tf_init_final_units_by_calls in target_info.flags) then
  261. begin
  262. inherited insert_init_final_table(entries);
  263. exit;
  264. end;
  265. initList:=TAsmList.create;
  266. finalList:=TAsmList.create;
  267. genentry(finalList);
  268. genentry(initList);
  269. for i:=0 to entries.count-1 do
  270. begin
  271. entry:=pinitfinalentry(entries[i]);
  272. if entry^.finifunc<>'' then
  273. finalList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.finifunc,AT_FUNCTION)));
  274. if entry^.initfunc<>'' then
  275. initList.Concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(entry^.initfunc,AT_FUNCTION)));
  276. end;
  277. genexit(finalList);
  278. genexit(initList);
  279. header:=TAsmList.create;
  280. new_section(header, sec_code, 'FPC_INIT_FUNC_TABLE', 1);
  281. header.concat(tai_symbol.Createname_global('FPC_INIT_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
  282. initList.insertList(header);
  283. header.free;
  284. current_asmdata.AsmLists[al_procedures].concatList(initList);
  285. header:=TAsmList.create;
  286. new_section(header, sec_code, 'FPC_FINALIZE_FUNC_TABLE', 1);
  287. header.concat(tai_symbol.Createname_global('FPC_FINALIZE_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
  288. finalList.insertList(header);
  289. header.free;
  290. current_asmdata.AsmLists[al_procedures].concatList(finalList);
  291. initList.Free;
  292. finalList.Free;
  293. inherited insert_init_final_table(entries);
  294. end;
  295. begin
  296. cnodeutils:=tarmnodeutils;
  297. end.