cg64f32.pas 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Member of the Free Pascal development team
  4. This unit implements the code generation for 64 bit int
  5. arithmethics on 32 bit processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. {# This unit implements the code generation for 64 bit int arithmethics on
  20. 32 bit processors.
  21. }
  22. unit cg64f32;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. aasmbase,aasmtai,aasmdata,aasmcpu,
  27. cpubase,cpupara,
  28. cgbase,cgobj,parabase,cgutils,
  29. symtype
  30. ;
  31. type
  32. {# Defines all the methods required on 32-bit processors
  33. to handle 64-bit integers.
  34. }
  35. tcg64f32 = class(tcg64)
  36. procedure a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);override;
  37. procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
  38. procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
  39. procedure a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);override;
  40. procedure a_load64_const_reg(list : TAsmList;value: int64;reg : tregister64);override;
  41. procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);override;
  42. procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);override;
  43. procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);override;
  44. procedure a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);override;
  45. procedure a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);override;
  46. procedure a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);override;
  47. procedure a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);override;
  48. procedure a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);override;
  49. procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);override;
  50. procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
  51. procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
  52. procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
  53. procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
  54. procedure a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
  55. procedure a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
  56. procedure a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
  57. procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
  58. procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
  59. procedure a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);override;
  60. procedure a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);override;
  61. procedure a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);override;
  62. procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
  63. procedure a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);override;
  64. procedure a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);override;
  65. procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
  66. procedure a_load64_loc_cgpara(list : TAsmList;const l : tlocation;const paraloc : tcgpara);override;
  67. procedure a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);override;
  68. procedure a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);override;
  69. {# This routine tries to optimize the a_op64_const_reg operation, by
  70. removing superfluous opcodes. Returns TRUE if normal processing
  71. must continue in op64_const_reg, otherwise, everything is processed
  72. entirely in this routine, by emitting the appropriate 32-bit opcodes.
  73. }
  74. function optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
  75. procedure g_rangecheck64(list: TAsmList; const l:tlocation;fromdef,todef: tdef); override;
  76. end;
  77. implementation
  78. uses
  79. globtype,systems,constexp,
  80. verbose,cutils,
  81. symbase,symconst,symdef,symtable,defutil,paramgr,
  82. tgobj,hlcgobj;
  83. {****************************************************************************
  84. Helpers
  85. ****************************************************************************}
  86. procedure swap64(var q : int64);
  87. begin
  88. q:=(int64(lo(q)) shl 32) or hi(q);
  89. end;
  90. procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
  91. var
  92. paraloclo,paraloclo2,paraloclo3,paraloclo4,
  93. paralochi,paralochi2,paralochi3,paralochi4 : pcgparalocation;
  94. curparaloc : PCGParaLocation;
  95. begin
  96. if not(cgpara.size in [OS_64,OS_S64]) then
  97. internalerror(200408231);
  98. if not assigned(cgpara.location) then
  99. internalerror(200408201);
  100. { init lo/hi para }
  101. cgparahi.reset;
  102. if cgpara.size=OS_S64 then
  103. cgparahi.size:=OS_S32
  104. else
  105. cgparahi.size:=OS_32;
  106. cgparahi.intsize:=4;
  107. cgparahi.alignment:=cgpara.alignment;
  108. paralochi:=cgparahi.add_location;
  109. cgparalo.reset;
  110. cgparalo.size:=OS_32;
  111. cgparalo.intsize:=4;
  112. cgparalo.alignment:=cgpara.alignment;
  113. paraloclo:=cgparalo.add_location;
  114. case cgpara.locations_count of
  115. 8:
  116. begin
  117. { 8 parameter fields? }
  118. { Order for multiple locations is always
  119. paraloc^ -> high
  120. paraloc^.next -> low }
  121. if (target_info.endian=ENDIAN_BIG) then
  122. begin
  123. { is there any big endian 8 bit ALU/16 bit Addr CPU? }
  124. internalerror(2015041001);
  125. { paraloc^ -> high }
  126. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  127. paralochi^.next:=nil;
  128. paralochi2:=cgparahi.add_location;
  129. move(cgpara.location^.next,paralochi2^,sizeof(paralochi2^));
  130. { paraloc^.next^.next^ -> low }
  131. move(cgpara.location^.next^.next^,paraloclo^,sizeof(paraloclo^));
  132. paraloclo^.next:=nil;
  133. paraloclo2:=cgparalo.add_location;
  134. move(cgpara.location^.next^.next^.next^,paraloclo2^,sizeof(paraloclo2^));
  135. end
  136. else
  137. begin
  138. { paraloc^ -> low }
  139. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  140. paraloclo^.next:=nil;
  141. paraloclo2:=cgparalo.add_location;
  142. move(cgpara.location^.next^,paraloclo2^,sizeof(paraloclo2^));
  143. paraloclo2^.next:=nil;
  144. paraloclo3:=cgparalo.add_location;
  145. move(cgpara.location^.next^.next^,paraloclo3^,sizeof(paraloclo3^));
  146. paraloclo3^.next:=nil;
  147. paraloclo4:=cgparalo.add_location;
  148. move(cgpara.location^.next^.next^.next^,paraloclo4^,sizeof(paraloclo4^));
  149. { paraloc^.next^.next^.next^.next^ -> high }
  150. curparaloc:=cgpara.location^.next^.next^.next^.next;
  151. move(curparaloc^,paralochi^,sizeof(paralochi^));
  152. paralochi^.next:=nil;
  153. paralochi2:=cgparahi.add_location;
  154. move(curparaloc^.next^,paralochi2^,sizeof(paralochi2^));
  155. paralochi2^.next:=nil;
  156. paralochi3:=cgparahi.add_location;
  157. move(curparaloc^.next^.next^,paralochi3^,sizeof(paralochi3^));
  158. paralochi3^.next:=nil;
  159. paralochi4:=cgparahi.add_location;
  160. move(curparaloc^.next^.next^.next^,paralochi4^,sizeof(paralochi4^));
  161. end;
  162. { fix size }
  163. paraloclo^.size:=OS_8;
  164. paraloclo2^.size:=OS_8;
  165. paraloclo3^.size:=OS_8;
  166. paraloclo4^.size:=OS_8;
  167. paraloclo4^.next:=nil;
  168. paralochi^.size:=OS_8;
  169. paralochi2^.size:=OS_8;
  170. paralochi3^.size:=OS_8;
  171. paralochi4^.size:=OS_8;
  172. paralochi4^.next:=nil;
  173. if cgpara.size=OS_S64 then
  174. if target_info.endian=ENDIAN_BIG then
  175. paralochi^.size:=OS_S8
  176. else
  177. paraloclo4^.size:=OS_S8;
  178. end;
  179. 4:
  180. begin
  181. { 4 parameter fields? }
  182. { Order for multiple locations is always
  183. paraloc^ -> high
  184. paraloc^.next -> low }
  185. if (target_info.endian=ENDIAN_BIG) then
  186. begin
  187. { paraloc^ -> high }
  188. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  189. paralochi^.next:=nil;
  190. paralochi2:=cgparahi.add_location;
  191. move(cgpara.location^.next,paralochi2^,sizeof(paralochi2^));
  192. { paraloc^.next^.next^ -> low }
  193. move(cgpara.location^.next^.next^,paraloclo^,sizeof(paraloclo^));
  194. paraloclo^.next:=nil;
  195. paraloclo2:=cgparalo.add_location;
  196. move(cgpara.location^.next^.next^.next^,paraloclo2^,sizeof(paraloclo2^));
  197. end
  198. else
  199. begin
  200. { paraloc^ -> low }
  201. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  202. paraloclo^.next:=nil;
  203. paraloclo2:=cgparalo.add_location;
  204. move(cgpara.location^.next^,paraloclo2^,sizeof(paraloclo2^));
  205. { paraloc^.next^.next -> high }
  206. move(cgpara.location^.next^.next^,paralochi^,sizeof(paralochi^));
  207. paralochi^.next:=nil;
  208. paralochi2:=cgparahi.add_location;
  209. move(cgpara.location^.next^.next^.next^,paralochi2^,sizeof(paralochi2^));
  210. end;
  211. { fix size }
  212. paraloclo^.size:=OS_16;
  213. paraloclo2^.size:=OS_16;
  214. paraloclo2^.next:=nil;
  215. paralochi^.size:=OS_16;
  216. paralochi2^.size:=OS_16;
  217. paralochi2^.next:=nil;
  218. if cgpara.size=OS_S64 then
  219. if target_info.endian=ENDIAN_BIG then
  220. paralochi^.size:=OS_S16
  221. else
  222. paraloclo2^.size:=OS_S16;
  223. end;
  224. 2:
  225. begin
  226. { 2 parameter fields? }
  227. { Order for multiple locations is always
  228. paraloc^ -> high
  229. paraloc^.next -> low }
  230. if (target_info.endian=ENDIAN_BIG) then
  231. begin
  232. { paraloc^ -> high
  233. paraloc^.next -> low }
  234. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  235. move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
  236. end
  237. else
  238. begin
  239. { paraloc^ -> low
  240. paraloc^.next -> high }
  241. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  242. move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
  243. end;
  244. { fix size }
  245. paraloclo^.size:=cgparalo.size;
  246. paraloclo^.next:=nil;
  247. paralochi^.size:=cgparahi.size;
  248. paralochi^.next:=nil;
  249. end;
  250. 1:
  251. begin
  252. { single parameter, this can only be in memory }
  253. if cgpara.location^.loc<>LOC_REFERENCE then
  254. internalerror(200408282);
  255. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  256. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  257. { for big endian low is at +4, for little endian high }
  258. if target_info.endian = endian_big then
  259. begin
  260. inc(cgparalo.location^.reference.offset,4);
  261. cgparalo.alignment:=newalignment(cgparalo.alignment,4);
  262. end
  263. else
  264. begin
  265. inc(cgparahi.location^.reference.offset,4);
  266. cgparahi.alignment:=newalignment(cgparahi.alignment,4);
  267. end;
  268. { fix size }
  269. paraloclo^.size:=cgparalo.size;
  270. paraloclo^.next:=nil;
  271. paralochi^.size:=cgparahi.size;
  272. paralochi^.next:=nil;
  273. end;
  274. else
  275. internalerror(2013051901);
  276. end;
  277. end;
  278. {****************************************************************************
  279. TCG64F32
  280. ****************************************************************************}
  281. procedure tcg64f32.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
  282. var
  283. tmpreg: tregister;
  284. tmpref: treference;
  285. begin
  286. if target_info.endian = endian_big then
  287. begin
  288. tmpreg:=reg.reglo;
  289. reg.reglo:=reg.reghi;
  290. reg.reghi:=tmpreg;
  291. end;
  292. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
  293. tmpref := ref;
  294. inc(tmpref.offset,4);
  295. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  296. end;
  297. procedure tcg64f32.a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);
  298. var
  299. tmpref: treference;
  300. begin
  301. if target_info.endian = endian_big then
  302. swap64(value);
  303. cg.a_load_const_ref(list,OS_32,longint(lo(value)),ref);
  304. tmpref := ref;
  305. inc(tmpref.offset,4);
  306. cg.a_load_const_ref(list,OS_32,longint(hi(value)),tmpref);
  307. end;
  308. procedure tcg64f32.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
  309. var
  310. tmpreg: tregister;
  311. tmpref: treference;
  312. begin
  313. if target_info.endian = endian_big then
  314. begin
  315. tmpreg := reg.reglo;
  316. reg.reglo := reg.reghi;
  317. reg.reghi := tmpreg;
  318. end;
  319. tmpref := ref;
  320. if (tmpref.base=reg.reglo) then
  321. begin
  322. tmpreg:=cg.getaddressregister(list);
  323. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  324. tmpref.base:=tmpreg;
  325. end
  326. else
  327. { this works only for the i386, thus the i386 needs to override }
  328. { this method and this method must be replaced by a more generic }
  329. { implementation FK }
  330. if (tmpref.index=reg.reglo) then
  331. begin
  332. tmpreg:=cg.getaddressregister(list);
  333. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
  334. tmpref.index:=tmpreg;
  335. end;
  336. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  337. inc(tmpref.offset,4);
  338. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  339. end;
  340. procedure tcg64f32.a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);
  341. begin
  342. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
  343. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
  344. end;
  345. procedure tcg64f32.a_load64_const_reg(list : TAsmList;value : int64;reg : tregister64);
  346. begin
  347. cg.a_load_const_reg(list,OS_32,longint(lo(value)),reg.reglo);
  348. cg.a_load_const_reg(list,OS_32,longint(hi(value)),reg.reghi);
  349. end;
  350. procedure tcg64f32.a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);
  351. var
  352. tmpreg: tregister;
  353. tmpsref: tsubsetreference;
  354. begin
  355. if (sref.bitindexreg <> NR_NO) or
  356. (sref.bitlen <> 64) then
  357. internalerror(2006082310);
  358. if (sref.startbit = 0) then
  359. begin
  360. a_load64_ref_reg(list,sref.ref,destreg);
  361. exit;
  362. end;
  363. if target_info.endian = endian_big then
  364. begin
  365. tmpreg := destreg.reglo;
  366. destreg.reglo := destreg.reghi;
  367. destreg.reghi := tmpreg;
  368. end;
  369. tmpsref:=sref;
  370. if (tmpsref.ref.base=destreg.reglo) then
  371. begin
  372. tmpreg:=cg.getaddressregister(list);
  373. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.base,tmpreg);
  374. tmpsref.ref.base:=tmpreg;
  375. end
  376. else
  377. if (tmpsref.ref.index=destreg.reglo) then
  378. begin
  379. tmpreg:=cg.getaddressregister(list);
  380. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.index,tmpreg);
  381. tmpsref.ref.index:=tmpreg;
  382. end;
  383. tmpsref.bitlen:=32;
  384. hlcg.a_load_subsetref_reg(list,u32inttype,u32inttype,tmpsref,destreg.reglo);
  385. inc(tmpsref.ref.offset,4);
  386. hlcg.a_load_subsetref_reg(list,u32inttype,u32inttype,tmpsref,destreg.reghi);
  387. end;
  388. procedure tcg64f32.a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);
  389. var
  390. tmpreg: tregister;
  391. tmpsref: tsubsetreference;
  392. begin
  393. if (sref.bitindexreg <> NR_NO) or
  394. (sref.bitlen <> 64) then
  395. internalerror(2006082311);
  396. if (sref.startbit = 0) then
  397. begin
  398. a_load64_reg_ref(list,fromreg,sref.ref);
  399. exit;
  400. end;
  401. if target_info.endian = endian_big then
  402. begin
  403. tmpreg:=fromreg.reglo;
  404. fromreg.reglo:=fromreg.reghi;
  405. fromreg.reghi:=tmpreg;
  406. end;
  407. tmpsref:=sref;
  408. tmpsref.bitlen:=32;
  409. hlcg.a_load_reg_subsetref(list,u32inttype,u32inttype,fromreg.reglo,tmpsref);
  410. inc(tmpsref.ref.offset,4);
  411. hlcg.a_load_reg_subsetref(list,u32inttype,u32inttype,fromreg.reghi,tmpsref);
  412. end;
  413. procedure tcg64f32.a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);
  414. var
  415. tmpsref: tsubsetreference;
  416. begin
  417. if (sref.bitindexreg <> NR_NO) or
  418. (sref.bitlen <> 64) then
  419. internalerror(2006082312);
  420. if target_info.endian = endian_big then
  421. swap64(a);
  422. tmpsref := sref;
  423. tmpsref.bitlen := 32;
  424. hlcg.a_load_const_subsetref(list,u32inttype,longint(lo(a)),tmpsref);
  425. inc(tmpsref.ref.offset,4);
  426. hlcg.a_load_const_subsetref(list,u32inttype,longint(hi(a)),tmpsref);
  427. end;
  428. procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
  429. var
  430. tmpreg64 : tregister64;
  431. begin
  432. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  433. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  434. a_load64_subsetref_reg(list,fromsref,tmpreg64);
  435. a_load64_reg_subsetref(list,tmpreg64,tosref);
  436. end;
  437. procedure tcg64f32.a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);
  438. var
  439. tmpreg64 : tregister64;
  440. begin
  441. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  442. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  443. a_load64_subsetref_reg(list,sref,tmpreg64);
  444. a_load64_reg_ref(list,tmpreg64,destref);
  445. end;
  446. procedure tcg64f32.a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);
  447. var
  448. tmpreg64 : tregister64;
  449. begin
  450. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  451. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  452. a_load64_ref_reg(list,fromref,tmpreg64);
  453. a_load64_reg_subsetref(list,tmpreg64,sref);
  454. end;
  455. procedure tcg64f32.a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);
  456. begin
  457. case l.loc of
  458. LOC_REFERENCE, LOC_CREFERENCE:
  459. a_load64_ref_reg(list,l.reference,reg);
  460. LOC_REGISTER,LOC_CREGISTER:
  461. a_load64_reg_reg(list,l.register64,reg);
  462. LOC_CONSTANT :
  463. a_load64_const_reg(list,l.value64,reg);
  464. LOC_SUBSETREF, LOC_CSUBSETREF:
  465. a_load64_subsetref_reg(list,l.sref,reg);
  466. else
  467. internalerror(200112292);
  468. end;
  469. end;
  470. procedure tcg64f32.a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);
  471. begin
  472. case l.loc of
  473. LOC_REGISTER,LOC_CREGISTER:
  474. a_load64_reg_ref(list,l.register64,ref);
  475. LOC_CONSTANT :
  476. a_load64_const_ref(list,l.value64,ref);
  477. LOC_SUBSETREF, LOC_CSUBSETREF:
  478. a_load64_subsetref_ref(list,l.sref,ref);
  479. else
  480. internalerror(200203288);
  481. end;
  482. end;
  483. procedure tcg64f32.a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);
  484. begin
  485. case l.loc of
  486. LOC_REFERENCE, LOC_CREFERENCE:
  487. a_load64_const_ref(list,value,l.reference);
  488. LOC_REGISTER,LOC_CREGISTER:
  489. a_load64_const_reg(list,value,l.register64);
  490. LOC_SUBSETREF, LOC_CSUBSETREF:
  491. a_load64_const_subsetref(list,value,l.sref);
  492. else
  493. internalerror(200112293);
  494. end;
  495. end;
  496. procedure tcg64f32.a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);
  497. begin
  498. case l.loc of
  499. LOC_REFERENCE, LOC_CREFERENCE:
  500. a_load64_reg_ref(list,reg,l.reference);
  501. LOC_REGISTER,LOC_CREGISTER:
  502. a_load64_reg_reg(list,reg,l.register64);
  503. LOC_SUBSETREF, LOC_CSUBSETREF:
  504. a_load64_reg_subsetref(list,reg,l.sref);
  505. LOC_MMREGISTER, LOC_CMMREGISTER:
  506. a_loadmm_intreg64_reg(list,l.size,reg,l.register);
  507. else
  508. internalerror(200112294);
  509. end;
  510. end;
  511. procedure tcg64f32.a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  512. var
  513. tmpref: treference;
  514. begin
  515. if target_info.endian = endian_big then
  516. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  517. else
  518. begin
  519. tmpref := ref;
  520. inc(tmpref.offset,4);
  521. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  522. end;
  523. end;
  524. procedure tcg64f32.a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  525. var
  526. tmpref: treference;
  527. begin
  528. if target_info.endian = endian_little then
  529. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  530. else
  531. begin
  532. tmpref := ref;
  533. inc(tmpref.offset,4);
  534. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  535. end;
  536. end;
  537. procedure tcg64f32.a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  538. var
  539. tmpref: treference;
  540. begin
  541. if target_info.endian = endian_big then
  542. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  543. else
  544. begin
  545. tmpref := ref;
  546. inc(tmpref.offset,4);
  547. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  548. end;
  549. end;
  550. procedure tcg64f32.a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  551. var
  552. tmpref: treference;
  553. begin
  554. if target_info.endian = endian_little then
  555. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  556. else
  557. begin
  558. tmpref := ref;
  559. inc(tmpref.offset,4);
  560. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  561. end;
  562. end;
  563. procedure tcg64f32.a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  564. begin
  565. case l.loc of
  566. LOC_REFERENCE,
  567. LOC_CREFERENCE :
  568. a_load64low_ref_reg(list,l.reference,reg);
  569. LOC_REGISTER,
  570. LOC_CREGISTER :
  571. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
  572. LOC_CONSTANT :
  573. cg.a_load_const_reg(list,OS_32,longint(lo(l.value64)),reg);
  574. else
  575. internalerror(200203244);
  576. end;
  577. end;
  578. procedure tcg64f32.a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  579. begin
  580. case l.loc of
  581. LOC_REFERENCE,
  582. LOC_CREFERENCE :
  583. a_load64high_ref_reg(list,l.reference,reg);
  584. LOC_REGISTER,
  585. LOC_CREGISTER :
  586. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
  587. LOC_CONSTANT :
  588. cg.a_load_const_reg(list,OS_32,longint(hi(l.value64)),reg);
  589. else
  590. internalerror(200203244);
  591. end;
  592. end;
  593. procedure tcg64f32.a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);
  594. begin
  595. case l.loc of
  596. LOC_REFERENCE, LOC_CREFERENCE:
  597. a_op64_const_ref(list,op,size,value,l.reference);
  598. LOC_REGISTER,LOC_CREGISTER:
  599. a_op64_const_reg(list,op,size,value,l.register64);
  600. else
  601. internalerror(200203292);
  602. end;
  603. end;
  604. procedure tcg64f32.a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);
  605. begin
  606. case l.loc of
  607. LOC_REFERENCE, LOC_CREFERENCE:
  608. a_op64_reg_ref(list,op,size,reg,l.reference);
  609. LOC_REGISTER,LOC_CREGISTER:
  610. a_op64_reg_reg(list,op,size,reg,l.register64);
  611. else
  612. internalerror(2002032422);
  613. end;
  614. end;
  615. procedure tcg64f32.a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);
  616. begin
  617. case l.loc of
  618. LOC_REFERENCE, LOC_CREFERENCE:
  619. a_op64_ref_reg(list,op,size,l.reference,reg);
  620. LOC_REGISTER,LOC_CREGISTER:
  621. a_op64_reg_reg(list,op,size,l.register64,reg);
  622. LOC_CONSTANT :
  623. a_op64_const_reg(list,op,size,l.value64,reg);
  624. else
  625. internalerror(200203242);
  626. end;
  627. end;
  628. procedure tcg64f32.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
  629. var
  630. tempreg: tregister64;
  631. begin
  632. tempreg.reghi:=cg.getintregister(list,OS_32);
  633. tempreg.reglo:=cg.getintregister(list,OS_32);
  634. a_load64_ref_reg(list,ref,tempreg);
  635. a_op64_reg_reg(list,op,size,tempreg,reg);
  636. end;
  637. procedure tcg64f32.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
  638. var
  639. tempreg: tregister64;
  640. begin
  641. tempreg.reghi:=cg.getintregister(list,OS_32);
  642. tempreg.reglo:=cg.getintregister(list,OS_32);
  643. if op in [OP_NEG,OP_NOT] then
  644. begin
  645. a_op64_reg_reg(list,op,size,reg,tempreg);
  646. a_load64_reg_ref(list,tempreg,ref);
  647. end
  648. else
  649. begin
  650. a_load64_ref_reg(list,ref,tempreg);
  651. a_op64_reg_reg(list,op,size,reg,tempreg);
  652. a_load64_reg_ref(list,tempreg,ref);
  653. end;
  654. end;
  655. procedure tcg64f32.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  656. var
  657. tempreg: tregister64;
  658. begin
  659. tempreg.reghi:=cg.getintregister(list,OS_32);
  660. tempreg.reglo:=cg.getintregister(list,OS_32);
  661. a_load64_ref_reg(list,ref,tempreg);
  662. a_op64_const_reg(list,op,size,value,tempreg);
  663. a_load64_reg_ref(list,tempreg,ref);
  664. end;
  665. procedure tcg64f32.a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);
  666. var
  667. tmplochi,tmploclo: tcgpara;
  668. begin
  669. tmploclo.init;
  670. tmplochi.init;
  671. splitparaloc64(paraloc,tmploclo,tmplochi);
  672. if target_info.endian=endian_big then
  673. begin
  674. { Keep this order of first lo before hi to have
  675. the correct push order for m68k }
  676. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  677. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  678. end
  679. else
  680. begin
  681. { Keep this order of first hi before lo to have
  682. the correct push order for i386 }
  683. cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
  684. cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
  685. end;
  686. tmploclo.done;
  687. tmplochi.done;
  688. end;
  689. procedure tcg64f32.a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);
  690. var
  691. tmplochi,tmploclo: tcgpara;
  692. begin
  693. tmploclo.init;
  694. tmplochi.init;
  695. splitparaloc64(paraloc,tmploclo,tmplochi);
  696. if target_info.endian=endian_big then
  697. begin
  698. { Keep this order of first lo before hi to have
  699. the correct push order for m68k }
  700. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  701. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  702. end
  703. else
  704. begin
  705. { Keep this order of first hi before lo to have
  706. the correct push order for i386 }
  707. cg.a_load_const_cgpara(list,OS_32,longint(hi(value)),tmplochi);
  708. cg.a_load_const_cgpara(list,OS_32,longint(lo(value)),tmploclo);
  709. end;
  710. tmploclo.done;
  711. tmplochi.done;
  712. end;
  713. procedure tcg64f32.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  714. var
  715. tmprefhi,tmpreflo : treference;
  716. tmploclo,tmplochi : tcgpara;
  717. begin
  718. tmploclo.init;
  719. tmplochi.init;
  720. splitparaloc64(paraloc,tmploclo,tmplochi);
  721. tmprefhi:=r;
  722. tmpreflo:=r;
  723. if target_info.endian=endian_big then
  724. begin
  725. { Keep this order of first lo before hi to have
  726. the correct push order for m68k }
  727. inc(tmpreflo.offset,4);
  728. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  729. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  730. end
  731. else
  732. begin
  733. { Keep this order of first hi before lo to have
  734. the correct push order for i386 }
  735. inc(tmprefhi.offset,4);
  736. cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
  737. cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
  738. end;
  739. tmploclo.done;
  740. tmplochi.done;
  741. end;
  742. procedure tcg64f32.a_load64_loc_cgpara(list : TAsmList;const l:tlocation;const paraloc : tcgpara);
  743. begin
  744. case l.loc of
  745. LOC_REGISTER,
  746. LOC_CREGISTER :
  747. a_load64_reg_cgpara(list,l.register64,paraloc);
  748. LOC_CONSTANT :
  749. a_load64_const_cgpara(list,l.value64,paraloc);
  750. LOC_CREFERENCE,
  751. LOC_REFERENCE :
  752. a_load64_ref_cgpara(list,l.reference,paraloc);
  753. else
  754. internalerror(200203287);
  755. end;
  756. end;
  757. procedure tcg64f32.a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);
  758. var
  759. tmpref: treference;
  760. begin
  761. if (tcgsize2size[mmsize]<>8) then
  762. internalerror(2009112501);
  763. tg.gettemp(list,8,8,tt_normal,tmpref);
  764. a_load64_reg_ref(list,intreg,tmpref);
  765. cg.a_loadmm_ref_reg(list,mmsize,mmsize,tmpref,mmreg,mms_movescalar);
  766. tg.ungettemp(list,tmpref);
  767. end;
  768. procedure tcg64f32.a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);
  769. var
  770. tmpref: treference;
  771. begin
  772. if (tcgsize2size[mmsize]<>8) then
  773. internalerror(2009112502);
  774. tg.gettemp(list,8,8,tt_normal,tmpref);
  775. cg.a_loadmm_reg_ref(list,mmsize,mmsize,mmreg,tmpref,mms_movescalar);
  776. a_load64_ref_reg(list,tmpref,intreg);
  777. tg.ungettemp(list,tmpref);
  778. end;
  779. procedure tcg64f32.g_rangecheck64(list : TAsmList;const l:tlocation;fromdef,todef:tdef);
  780. var
  781. neglabel,
  782. poslabel,
  783. endlabel: tasmlabel;
  784. hreg : tregister;
  785. hdef : torddef;
  786. opsize : tcgsize;
  787. from_signed,to_signed: boolean;
  788. temploc : tlocation;
  789. begin
  790. from_signed := is_signed(fromdef);
  791. to_signed := is_signed(todef);
  792. if not is_64bit(todef) then
  793. begin
  794. { get the high dword in a register }
  795. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  796. begin
  797. hreg := l.register64.reghi;
  798. end
  799. else
  800. begin
  801. hreg:=cg.getintregister(list,OS_32);
  802. a_load64high_ref_reg(list,l.reference,hreg);
  803. end;
  804. current_asmdata.getjumplabel(poslabel);
  805. { check high dword, must be 0 (for positive numbers) }
  806. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  807. { It can also be $ffffffff, but only for negative numbers }
  808. if from_signed and to_signed then
  809. begin
  810. current_asmdata.getjumplabel(neglabel);
  811. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  812. end
  813. else
  814. { we do not have dynamic dfa, so avoid a warning below about the unused
  815. neglabel }
  816. neglabel:=nil;
  817. { For all other values we have a range check error }
  818. cg.a_call_name(list,'fpc_rangeerror',false);
  819. { if the high dword = 0, the low dword can be considered a }
  820. { simple cardinal }
  821. cg.a_label(list,poslabel);
  822. hdef:=corddef.create(u32bit,0,$ffffffff,false);
  823. location_copy(temploc,l);
  824. temploc.size:=OS_32;
  825. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  826. (target_info.endian = endian_big) then
  827. begin
  828. inc(temploc.reference.offset,4);
  829. temploc.reference.alignment:=newalignment(temploc.reference.alignment,4);
  830. end;
  831. hlcg.g_rangecheck(list,temploc,hdef,todef);
  832. hdef.free;
  833. if from_signed and to_signed then
  834. begin
  835. current_asmdata.getjumplabel(endlabel);
  836. cg.a_jmp_always(list,endlabel);
  837. { if the high dword = $ffffffff, then the low dword (when }
  838. { considered as a longint) must be < 0 }
  839. cg.a_label(list,neglabel);
  840. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  841. begin
  842. hreg := l.register64.reglo;
  843. end
  844. else
  845. begin
  846. hreg:=cg.getintregister(list,OS_32);
  847. a_load64low_ref_reg(list,l.reference,hreg);
  848. end;
  849. { get a new neglabel (JM) }
  850. current_asmdata.getjumplabel(neglabel);
  851. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  852. cg.a_call_name(list,'fpc_rangeerror',false);
  853. { if we get here, the 64bit value lies between }
  854. { longint($80000000) and -1 (JM) }
  855. cg.a_label(list,neglabel);
  856. hdef:=corddef.create(s32bit,int64(longint($80000000)),int64(-1),false);
  857. location_copy(temploc,l);
  858. temploc.size:=OS_32;
  859. hlcg.g_rangecheck(list,temploc,hdef,todef);
  860. hdef.free;
  861. cg.a_label(list,endlabel);
  862. end;
  863. end
  864. else
  865. { todef = 64bit int }
  866. { no 64bit subranges supported, so only a small check is necessary }
  867. { if both are signed or both are unsigned, no problem! }
  868. if (from_signed xor to_signed) and
  869. { also not if the fromdef is unsigned and < 64bit, since that will }
  870. { always fit in a 64bit int (todef is 64bit) }
  871. (from_signed or
  872. (torddef(fromdef).ordtype = u64bit)) then
  873. begin
  874. { in all cases, there is only a problem if the higest bit is set }
  875. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  876. begin
  877. if is_64bit(fromdef) then
  878. begin
  879. hreg := l.register64.reghi;
  880. opsize := OS_32;
  881. end
  882. else
  883. begin
  884. hreg := l.register;
  885. opsize := def_cgsize(fromdef);
  886. end;
  887. end
  888. else
  889. begin
  890. hreg:=cg.getintregister(list,OS_32);
  891. opsize:=OS_32;
  892. if l.size in [OS_64,OS_S64] then
  893. a_load64high_ref_reg(list,l.reference,hreg)
  894. else
  895. cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
  896. end;
  897. current_asmdata.getjumplabel(poslabel);
  898. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  899. cg.a_call_name(list,'fpc_rangeerror',false);
  900. cg.a_label(list,poslabel);
  901. end;
  902. end;
  903. function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
  904. var
  905. lowvalue, highvalue : longint;
  906. hreg: tregister;
  907. begin
  908. lowvalue := longint(a);
  909. highvalue:= longint(a shr 32);
  910. { assume it will be optimized out }
  911. optimize64_op_const_reg := true;
  912. case op of
  913. OP_ADD:
  914. begin
  915. if a = 0 then
  916. exit;
  917. end;
  918. OP_AND:
  919. begin
  920. if lowvalue <> -1 then
  921. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  922. if highvalue <> -1 then
  923. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  924. { already emitted correctly }
  925. exit;
  926. end;
  927. OP_OR:
  928. begin
  929. if lowvalue <> 0 then
  930. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  931. if highvalue <> 0 then
  932. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  933. { already emitted correctly }
  934. exit;
  935. end;
  936. OP_SUB:
  937. begin
  938. if a = 0 then
  939. exit;
  940. end;
  941. OP_XOR:
  942. begin
  943. end;
  944. OP_SHL:
  945. begin
  946. if a = 0 then
  947. exit;
  948. { simply clear low-register
  949. and shift the rest and swap
  950. registers.
  951. }
  952. if (a > 31) then
  953. begin
  954. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  955. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  956. { swap the registers }
  957. hreg := reg.reghi;
  958. reg.reghi := reg.reglo;
  959. reg.reglo := hreg;
  960. exit;
  961. end;
  962. end;
  963. OP_SHR:
  964. begin
  965. if a = 0 then exit;
  966. { simply clear high-register
  967. and shift the rest and swap
  968. registers.
  969. }
  970. if (a > 31) then
  971. begin
  972. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  973. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  974. { swap the registers }
  975. hreg := reg.reghi;
  976. reg.reghi := reg.reglo;
  977. reg.reglo := hreg;
  978. exit;
  979. end;
  980. end;
  981. OP_IMUL,OP_MUL:
  982. begin
  983. if a = 1 then exit;
  984. end;
  985. OP_IDIV,OP_DIV:
  986. begin
  987. if a = 1 then exit;
  988. end;
  989. else
  990. internalerror(20020817);
  991. end;
  992. optimize64_op_const_reg := false;
  993. end;
  994. end.