n68kinl.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. {
  2. Copyright (c) 2015 by the Free Pascal Development team
  3. Generates Motorola 68k 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 n68kinl;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,ninl,ncginl,cpubase;
  22. type
  23. t68kinlinenode = class(tcgInlineNode)
  24. function first_abs_real: tnode; override;
  25. function first_sqr_real: tnode; override;
  26. function first_sqrt_real: tnode; override;
  27. {function first_arctan_real: tnode; override;
  28. function first_ln_real: tnode; override;}
  29. function first_cos_real: tnode; override;
  30. function first_sin_real: tnode; override;
  31. function first_int_real: tnode; override;
  32. function first_frac_real: tnode; override;
  33. procedure second_abs_real; override;
  34. procedure second_sqr_real; override;
  35. procedure second_sqrt_real; override;
  36. {procedure second_arctan_real; override;
  37. procedure second_ln_real; override;}
  38. procedure second_cos_real; override;
  39. procedure second_sin_real; override;
  40. procedure second_int_real; override;
  41. procedure second_frac_real; override;
  42. {procedure second_prefetch; override;
  43. procedure second_abs_long; override;}
  44. private
  45. procedure second_do_operation(op: TAsmOp);
  46. end;
  47. implementation
  48. uses
  49. globtype,verbose,globals,cutils,
  50. cpuinfo,defutil,symdef,aasmdata,aasmcpu,aasmtai,
  51. cgbase,cgutils,pass_1,pass_2,
  52. ncgutil,cgobj,cgcpu,hlcgobj;
  53. {*****************************************************************************
  54. t68kinlinenode
  55. *****************************************************************************}
  56. function t68kinlinenode.first_abs_real : tnode;
  57. begin
  58. if (cs_fp_emulation in current_settings.moduleswitches) then
  59. result:=inherited first_abs_real
  60. else
  61. begin
  62. case current_settings.fputype of
  63. fpu_68881,fpu_coldfire:
  64. expectloc:=LOC_FPUREGISTER;
  65. else
  66. internalerror(2015022206);
  67. end;
  68. first_abs_real:=nil;
  69. end;
  70. end;
  71. function t68kinlinenode.first_sqr_real : tnode;
  72. begin
  73. if (cs_fp_emulation in current_settings.moduleswitches) then
  74. result:=inherited first_sqr_real
  75. else
  76. begin
  77. case current_settings.fputype of
  78. fpu_68881,fpu_coldfire:
  79. expectloc:=LOC_FPUREGISTER;
  80. else
  81. internalerror(2015022201);
  82. end;
  83. first_sqr_real:=nil;
  84. end;
  85. end;
  86. function t68kinlinenode.first_sqrt_real : tnode;
  87. begin
  88. if (cs_fp_emulation in current_settings.moduleswitches) then
  89. result:=inherited first_sqrt_real
  90. else
  91. begin
  92. case current_settings.fputype of
  93. fpu_68881,fpu_coldfire:
  94. expectloc:=LOC_FPUREGISTER;
  95. else
  96. internalerror(2015022203);
  97. end;
  98. first_sqrt_real:=nil;
  99. end;
  100. end;
  101. function t68kinlinenode.first_sin_real : tnode;
  102. begin
  103. if (cs_fp_emulation in current_settings.moduleswitches) then
  104. result:=inherited first_sin_real
  105. else
  106. begin
  107. case current_settings.fputype of
  108. fpu_68881:
  109. expectloc:=LOC_FPUREGISTER;
  110. fpu_soft,fpu_coldfire:
  111. begin
  112. result:=inherited first_sin_real;
  113. exit;
  114. end;
  115. else
  116. internalerror(2015022203);
  117. end;
  118. first_sin_real:=nil;
  119. end;
  120. end;
  121. function t68kinlinenode.first_cos_real : tnode;
  122. begin
  123. if (cs_fp_emulation in current_settings.moduleswitches) then
  124. result:=inherited first_cos_real
  125. else
  126. begin
  127. case current_settings.fputype of
  128. fpu_68881:
  129. expectloc:=LOC_FPUREGISTER;
  130. fpu_soft,fpu_coldfire:
  131. begin
  132. result:=inherited first_cos_real;
  133. exit;
  134. end;
  135. else
  136. internalerror(2015022203);
  137. end;
  138. first_cos_real:=nil;
  139. end;
  140. end;
  141. function t68kinlinenode.first_int_real : tnode;
  142. begin
  143. if (cs_fp_emulation in current_settings.moduleswitches) then
  144. result:=inherited first_int_real
  145. else
  146. begin
  147. case current_settings.fputype of
  148. fpu_68881,fpu_coldfire:
  149. expectloc:=LOC_FPUREGISTER;
  150. else
  151. internalerror(2016112701);
  152. end;
  153. first_int_real:=nil;
  154. end;
  155. end;
  156. function t68kinlinenode.first_frac_real : tnode;
  157. begin
  158. if (cs_fp_emulation in current_settings.moduleswitches) then
  159. result:=inherited first_frac_real
  160. else
  161. begin
  162. case current_settings.fputype of
  163. fpu_68881,fpu_coldfire:
  164. expectloc:=LOC_FPUREGISTER;
  165. else
  166. internalerror(2017052103);
  167. end;
  168. first_frac_real:=nil;
  169. end;
  170. end;
  171. procedure t68kinlinenode.second_abs_real;
  172. begin
  173. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_abs_real called!')));
  174. second_do_operation(A_FABS);
  175. end;
  176. procedure t68kinlinenode.second_sqr_real;
  177. begin
  178. secondpass(left);
  179. case current_settings.fputype of
  180. fpu_68881,fpu_coldfire:
  181. begin
  182. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_sqr_real called!')));
  183. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  184. location_copy(location,left.location);
  185. if left.location.loc=LOC_CFPUREGISTER then
  186. begin
  187. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_srq_real called!: left was cfpuregister!')));
  188. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  189. location.loc := LOC_FPUREGISTER;
  190. cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register);
  191. end;
  192. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FMUL,fpuregopsize,left.location.register,location.register));
  193. end;
  194. else
  195. internalerror(2015022202);
  196. end;
  197. end;
  198. procedure t68kinlinenode.second_sqrt_real;
  199. begin
  200. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_sqrt_real called!')));
  201. second_do_operation(A_FSQRT);
  202. end;
  203. procedure t68kinlinenode.second_sin_real;
  204. begin
  205. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_sin_real called!')));
  206. second_do_operation(A_FSIN);
  207. end;
  208. procedure t68kinlinenode.second_cos_real;
  209. begin
  210. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_cos_real called!')));
  211. second_do_operation(A_FCOS);
  212. end;
  213. procedure t68kinlinenode.second_int_real;
  214. begin
  215. //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_int_real called!')));
  216. second_do_operation(A_FINTRZ);
  217. end;
  218. procedure t68kinlinenode.second_do_operation(op: TAsmOp);
  219. var
  220. href: TReference;
  221. begin
  222. secondpass(left);
  223. case current_settings.fputype of
  224. fpu_68881,fpu_coldfire:
  225. begin
  226. location_reset(location,LOC_FPUREGISTER,left.location.size);
  227. case left.location.loc of
  228. LOC_FPUREGISTER:
  229. begin
  230. location.register:=left.location.register;
  231. current_asmdata.CurrAsmList.concat(taicpu.op_reg(op,fpuregopsize,location.register))
  232. end;
  233. LOC_CFPUREGISTER:
  234. begin
  235. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  236. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,fpuregopsize,left.location.register,location.register));
  237. end;
  238. LOC_REFERENCE,LOC_CREFERENCE:
  239. begin
  240. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  241. href:=left.location.reference;
  242. tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,current_settings.fputype = fpu_coldfire);
  243. current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,tcgsize2opsize[left.location.size],href,location.register));
  244. end;
  245. else
  246. internalerror(2015022205);
  247. end;
  248. end;
  249. else
  250. internalerror(2015022204);
  251. end;
  252. end;
  253. procedure t68kinlinenode.second_frac_real;
  254. var
  255. href: TReference;
  256. hreg: TRegister;
  257. begin
  258. secondpass(left);
  259. case current_settings.fputype of
  260. fpu_68881,fpu_coldfire:
  261. begin
  262. location_reset(location,LOC_FPUREGISTER,left.location.size);
  263. case left.location.loc of
  264. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  265. begin
  266. hreg:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  267. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  268. cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register);
  269. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FINTRZ,fpuregopsize,left.location.register,hreg));
  270. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSUB,fpuregopsize,hreg,location.register));
  271. end;
  272. LOC_REFERENCE,LOC_CREFERENCE:
  273. begin
  274. hreg:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  275. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  276. href:=left.location.reference;
  277. tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,current_settings.fputype = fpu_coldfire);
  278. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,href,location.register);
  279. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FINTRZ,fpuregopsize,location.register,hreg));
  280. current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSUB,fpuregopsize,hreg,location.register));
  281. end;
  282. else
  283. internalerror(2017052101);
  284. end;
  285. end;
  286. else
  287. internalerror(2017052102);
  288. end;
  289. end;
  290. { ideas for second_abs_long (KB) }
  291. { This is probably faster on 68000 than the generic implementation,
  292. because shifting is slow on the original 68000, maybe also on the 68020?
  293. Also needs to be tested on 040/060. This can also work on a CF.
  294. input - d0, output - d2
  295. move.l d0,d2
  296. btst #31,d2
  297. sne d1
  298. extb.l d1 (or ext.w + ext.l on 68000)
  299. eor.l d1,d2
  300. sub.l d1,d2
  301. }
  302. { Solution using bitfield extraction, we don't support the necessary asm
  303. construct for this yet, probably this is the fastest on 020, slower on
  304. 040/060 than the one above, doesn't work on '000 or CF.
  305. input - d0, output - d2
  306. move.l d0,d2
  307. bfexts d0[0:1],d1
  308. eor.l d1,d2
  309. sub.l d1,d2
  310. }
  311. begin
  312. cinlinenode:=t68kinlinenode;
  313. end.