narminl.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generates ARM inline nodes
  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 narminl;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,ninl,ncginl;
  22. type
  23. tarminlinenode = class(tcgInlineNode)
  24. function first_abs_real: tnode; override;
  25. function first_sqr_real: tnode; override;
  26. function first_sqrt_real: tnode; override;
  27. { atn,sin,cos,lgn isn't supported by the linux fpe
  28. function first_arctan_real: tnode; override;
  29. function first_ln_real: tnode; override;
  30. function first_cos_real: tnode; override;
  31. function first_sin_real: tnode; override;
  32. }
  33. procedure second_abs_real; override;
  34. procedure second_sqr_real; override;
  35. procedure second_sqrt_real; override;
  36. { atn,sin,cos,lgn isn't supported by the linux fpe
  37. procedure second_arctan_real; override;
  38. procedure second_ln_real; override;
  39. procedure second_cos_real; override;
  40. procedure second_sin_real; override;
  41. }
  42. procedure second_prefetch; override;
  43. procedure second_abs_long; override;
  44. private
  45. procedure load_fpu_location(out singleprec: boolean);
  46. end;
  47. implementation
  48. uses
  49. globtype,verbose,globals,
  50. cpuinfo, defutil,symdef,aasmdata,aasmcpu,
  51. cgbase,cgutils,pass_1,pass_2,
  52. cpubase,ncgutil,cgobj,cgcpu, hlcgobj;
  53. {*****************************************************************************
  54. tarminlinenode
  55. *****************************************************************************}
  56. procedure tarminlinenode.load_fpu_location(out singleprec: boolean);
  57. begin
  58. secondpass(left);
  59. case current_settings.fputype of
  60. fpu_fpa,
  61. fpu_fpa10,
  62. fpu_fpa11:
  63. begin
  64. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  65. location_copy(location,left.location);
  66. if left.location.loc=LOC_CFPUREGISTER then
  67. begin
  68. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  69. location.loc := LOC_FPUREGISTER;
  70. end;
  71. end;
  72. fpu_vfpv2,
  73. fpu_vfpv3,
  74. fpu_vfpv3_d16,
  75. fpu_fpv4_s16:
  76. begin
  77. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  78. location_copy(location,left.location);
  79. if left.location.loc=LOC_CMMREGISTER then
  80. begin
  81. location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
  82. location.loc := LOC_MMREGISTER;
  83. end;
  84. end;
  85. fpu_soft:
  86. begin
  87. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  88. location_copy(location,left.location);
  89. end
  90. else
  91. internalerror(2009111801);
  92. end;
  93. singleprec:=tfloatdef(left.resultdef).floattype=s32real;
  94. end;
  95. function tarminlinenode.first_abs_real : tnode;
  96. begin
  97. if (cs_fp_emulation in current_settings.moduleswitches) then
  98. begin
  99. firstpass(left);
  100. expectloc:=LOC_REGISTER;
  101. first_abs_real:=nil;
  102. end
  103. else
  104. begin
  105. case current_settings.fputype of
  106. fpu_fpa,
  107. fpu_fpa10,
  108. fpu_fpa11:
  109. expectloc:=LOC_FPUREGISTER;
  110. fpu_vfpv2,
  111. fpu_vfpv3,
  112. fpu_vfpv3_d16:
  113. expectloc:=LOC_MMREGISTER;
  114. fpu_fpv4_s16:
  115. begin
  116. if tfloatdef(left.resultdef).floattype=s32real then
  117. expectloc:=LOC_MMREGISTER
  118. else
  119. exit(inherited first_abs_real);
  120. end;
  121. else
  122. internalerror(2009112401);
  123. end;
  124. first_abs_real:=nil;
  125. end;
  126. end;
  127. function tarminlinenode.first_sqr_real : tnode;
  128. begin
  129. if (cs_fp_emulation in current_settings.moduleswitches) then
  130. result:=inherited first_sqr_real
  131. else
  132. begin
  133. case current_settings.fputype of
  134. fpu_fpa,
  135. fpu_fpa10,
  136. fpu_fpa11:
  137. expectloc:=LOC_FPUREGISTER;
  138. fpu_vfpv2,
  139. fpu_vfpv3,
  140. fpu_vfpv3_d16:
  141. expectloc:=LOC_MMREGISTER;
  142. fpu_fpv4_s16:
  143. begin
  144. if tfloatdef(left.resultdef).floattype=s32real then
  145. expectloc:=LOC_MMREGISTER
  146. else
  147. exit(inherited first_sqr_real);
  148. end;
  149. else
  150. internalerror(2009112402);
  151. end;
  152. first_sqr_real:=nil;
  153. end;
  154. end;
  155. function tarminlinenode.first_sqrt_real : tnode;
  156. begin
  157. if cs_fp_emulation in current_settings.moduleswitches then
  158. result:=inherited first_sqrt_real
  159. else
  160. begin
  161. case current_settings.fputype of
  162. fpu_fpa,
  163. fpu_fpa10,
  164. fpu_fpa11:
  165. expectloc:=LOC_FPUREGISTER;
  166. fpu_vfpv2,
  167. fpu_vfpv3,
  168. fpu_vfpv3_d16:
  169. expectloc:=LOC_MMREGISTER;
  170. fpu_fpv4_s16:
  171. begin
  172. if tfloatdef(left.resultdef).floattype=s32real then
  173. expectloc:=LOC_MMREGISTER
  174. else
  175. exit(inherited first_sqrt_real);
  176. end;
  177. else
  178. internalerror(2009112403);
  179. end;
  180. first_sqrt_real := nil;
  181. end;
  182. end;
  183. { atn,sin,cos,lgn isn't supported by the linux fpe
  184. function tarminlinenode.first_arctan_real: tnode;
  185. begin
  186. expectloc:=LOC_FPUREGISTER;
  187. result:=nil;
  188. end;
  189. function tarminlinenode.first_ln_real: tnode;
  190. begin
  191. expectloc:=LOC_FPUREGISTER;
  192. result:=nil;
  193. end;
  194. function tarminlinenode.first_cos_real: tnode;
  195. begin
  196. expectloc:=LOC_FPUREGISTER;
  197. result:=nil;
  198. end;
  199. function tarminlinenode.first_sin_real: tnode;
  200. begin
  201. expectloc:=LOC_FPUREGISTER;
  202. result:=nil;
  203. end;
  204. }
  205. procedure tarminlinenode.second_abs_real;
  206. var
  207. singleprec: boolean;
  208. op: TAsmOp;
  209. begin
  210. load_fpu_location(singleprec);
  211. case current_settings.fputype of
  212. fpu_fpa,
  213. fpu_fpa10,
  214. fpu_fpa11:
  215. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_ABS,location.register,left.location.register),get_fpu_postfix(resultdef)));
  216. fpu_vfpv2,
  217. fpu_vfpv3,
  218. fpu_vfpv3_d16:
  219. begin
  220. if singleprec then
  221. op:=A_FABSS
  222. else
  223. op:=A_FABSD;
  224. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
  225. end;
  226. fpu_fpv4_s16:
  227. current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32));
  228. fpu_soft:
  229. begin
  230. if singleprec then
  231. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_32,tcgint($7fffffff),location.register)
  232. else
  233. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_32,tcgint($7fffffff),location.registerhi);
  234. end
  235. else
  236. internalerror(2009111402);
  237. end;
  238. end;
  239. procedure tarminlinenode.second_sqr_real;
  240. var
  241. singleprec: boolean;
  242. op: TAsmOp;
  243. begin
  244. load_fpu_location(singleprec);
  245. case current_settings.fputype of
  246. fpu_fpa,
  247. fpu_fpa10,
  248. fpu_fpa11:
  249. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_MUF,location.register,left.location.register,left.location.register),get_fpu_postfix(resultdef)));
  250. fpu_vfpv2,
  251. fpu_vfpv3,
  252. fpu_vfpv3_d16:
  253. begin
  254. if singleprec then
  255. op:=A_FMULS
  256. else
  257. op:=A_FMULD;
  258. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
  259. end;
  260. fpu_fpv4_s16:
  261. current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register), PF_F32));
  262. else
  263. internalerror(2009111403);
  264. end;
  265. end;
  266. procedure tarminlinenode.second_sqrt_real;
  267. var
  268. singleprec: boolean;
  269. op: TAsmOp;
  270. begin
  271. load_fpu_location(singleprec);
  272. case current_settings.fputype of
  273. fpu_fpa,
  274. fpu_fpa10,
  275. fpu_fpa11:
  276. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_SQT,location.register,left.location.register),get_fpu_postfix(resultdef)));
  277. fpu_vfpv2,
  278. fpu_vfpv3,
  279. fpu_vfpv3_d16:
  280. begin
  281. if singleprec then
  282. op:=A_FSQRTS
  283. else
  284. op:=A_FSQRTD;
  285. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
  286. end;
  287. fpu_fpv4_s16:
  288. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register));
  289. else
  290. internalerror(2009111402);
  291. end;
  292. end;
  293. { atn, sin, cos, lgn isn't supported by the linux fpe
  294. procedure tarminlinenode.second_arctan_real;
  295. begin
  296. load_fpu_location;
  297. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_ATN,location.register,left.location.register),get_fpu_postfix(resultdef)));
  298. end;
  299. procedure tarminlinenode.second_ln_real;
  300. begin
  301. load_fpu_location;
  302. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_LGN,location.register,left.location.register),get_fpu_postfix(resultdef)));
  303. end;
  304. procedure tarminlinenode.second_cos_real;
  305. begin
  306. load_fpu_location;
  307. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_COS,location.register,left.location.register),get_fpu_postfix(resultdef)));
  308. end;
  309. procedure tarminlinenode.second_sin_real;
  310. begin
  311. load_fpu_location;
  312. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_SIN,location.register,left.location.register),get_fpu_postfix(resultdef)));
  313. end;
  314. }
  315. procedure tarminlinenode.second_prefetch;
  316. var
  317. ref : treference;
  318. r : tregister;
  319. begin
  320. if not(GenerateThumbCode) and (CPUARM_HAS_EDSP in cpu_capabilities[current_settings.cputype]) then
  321. begin
  322. secondpass(left);
  323. case left.location.loc of
  324. LOC_CREFERENCE,
  325. LOC_REFERENCE:
  326. begin
  327. r:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
  328. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,r);
  329. reference_reset_base(ref,r,0,left.location.reference.alignment);
  330. { since the address might be nil we can't use ldr for older cpus }
  331. current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_PLD,ref));
  332. end;
  333. else
  334. internalerror(200402021);
  335. end;
  336. end;
  337. end;
  338. procedure tarminlinenode.second_abs_long;
  339. var
  340. opsize : tcgsize;
  341. hp : taicpu;
  342. begin
  343. if GenerateThumbCode then
  344. begin
  345. inherited second_abs_long;
  346. exit;
  347. end;
  348. secondpass(left);
  349. opsize:=def_cgsize(left.resultdef);
  350. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  351. location:=left.location;
  352. location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
  353. cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  354. current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MOV,location.register,left.location.register), PF_S));
  355. if GenerateThumb2Code then
  356. current_asmdata.CurrAsmList.concat(taicpu.op_cond(A_IT,C_MI));
  357. current_asmdata.CurrAsmList.concat(setcondition(taicpu.op_reg_reg_const(A_RSB,location.register,location.register, 0), C_MI));
  358. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  359. end;
  360. begin
  361. cinlinenode:=tarminlinenode;
  362. end.