cg64f32.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  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_param64_reg(list : TAsmList;reg : tregister64;const paraloc : tcgpara);override;
  64. procedure a_param64_const(list : TAsmList;value : int64;const paraloc : tcgpara);override;
  65. procedure a_param64_ref(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
  66. procedure a_param64_loc(list : TAsmList;const l : tlocation;const paraloc : tcgpara);override;
  67. {# This routine tries to optimize the a_op64_const_reg operation, by
  68. removing superfluous opcodes. Returns TRUE if normal processing
  69. must continue in op64_const_reg, otherwise, everything is processed
  70. entirely in this routine, by emitting the appropriate 32-bit opcodes.
  71. }
  72. function optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
  73. procedure g_rangecheck64(list: TAsmList; const l:tlocation;fromdef,todef: tdef); override;
  74. end;
  75. {# Creates a tregister64 record from 2 32 Bit registers. }
  76. function joinreg64(reglo,reghi : tregister) : tregister64;
  77. implementation
  78. uses
  79. globtype,systems,constexp,
  80. verbose,cutils,
  81. symbase,symconst,symdef,symtable,defutil,paramgr;
  82. {****************************************************************************
  83. Helpers
  84. ****************************************************************************}
  85. function joinreg64(reglo,reghi : tregister) : tregister64;
  86. begin
  87. result.reglo:=reglo;
  88. result.reghi:=reghi;
  89. end;
  90. procedure swap64(var q : int64);
  91. begin
  92. q:=(int64(lo(q)) shl 32) or hi(q);
  93. end;
  94. procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
  95. var
  96. paraloclo,
  97. paralochi : pcgparalocation;
  98. begin
  99. if not(cgpara.size in [OS_64,OS_S64]) then
  100. internalerror(200408231);
  101. if not assigned(cgpara.location) then
  102. internalerror(200408201);
  103. { init lo/hi para }
  104. cgparahi.reset;
  105. if cgpara.size=OS_S64 then
  106. cgparahi.size:=OS_S32
  107. else
  108. cgparahi.size:=OS_32;
  109. cgparahi.intsize:=4;
  110. cgparahi.alignment:=cgpara.alignment;
  111. paralochi:=cgparahi.add_location;
  112. cgparalo.reset;
  113. cgparalo.size:=OS_32;
  114. cgparalo.intsize:=4;
  115. cgparalo.alignment:=cgpara.alignment;
  116. paraloclo:=cgparalo.add_location;
  117. { 2 parameter fields? }
  118. if assigned(cgpara.location^.next) then
  119. begin
  120. { Order for multiple locations is always
  121. paraloc^ -> high
  122. paraloc^.next -> low }
  123. if (target_info.endian=ENDIAN_BIG) then
  124. begin
  125. { paraloc^ -> high
  126. paraloc^.next -> low }
  127. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  128. move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
  129. end
  130. else
  131. begin
  132. { paraloc^ -> low
  133. paraloc^.next -> high }
  134. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  135. move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
  136. end;
  137. end
  138. else
  139. begin
  140. { single parameter, this can only be in memory }
  141. if cgpara.location^.loc<>LOC_REFERENCE then
  142. internalerror(200408282);
  143. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  144. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  145. { for big endian low is at +4, for little endian high }
  146. if target_info.endian = endian_big then
  147. begin
  148. inc(cgparalo.location^.reference.offset,4);
  149. cgparalo.alignment:=newalignment(cgparalo.alignment,4);
  150. end
  151. else
  152. begin
  153. inc(cgparahi.location^.reference.offset,4);
  154. cgparahi.alignment:=newalignment(cgparahi.alignment,4);
  155. end;
  156. end;
  157. { fix size }
  158. paraloclo^.size:=cgparalo.size;
  159. paraloclo^.next:=nil;
  160. paralochi^.size:=cgparahi.size;
  161. paralochi^.next:=nil;
  162. end;
  163. {****************************************************************************
  164. TCG64F32
  165. ****************************************************************************}
  166. procedure tcg64f32.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
  167. var
  168. tmpreg: tregister;
  169. tmpref: treference;
  170. begin
  171. if target_info.endian = endian_big then
  172. begin
  173. tmpreg:=reg.reglo;
  174. reg.reglo:=reg.reghi;
  175. reg.reghi:=tmpreg;
  176. end;
  177. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
  178. tmpref := ref;
  179. inc(tmpref.offset,4);
  180. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  181. end;
  182. procedure tcg64f32.a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);
  183. var
  184. tmpref: treference;
  185. begin
  186. if target_info.endian = endian_big then
  187. swap64(value);
  188. cg.a_load_const_ref(list,OS_32,aint(lo(value)),ref);
  189. tmpref := ref;
  190. inc(tmpref.offset,4);
  191. cg.a_load_const_ref(list,OS_32,aint(hi(value)),tmpref);
  192. end;
  193. procedure tcg64f32.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
  194. var
  195. tmpreg: tregister;
  196. tmpref: treference;
  197. begin
  198. if target_info.endian = endian_big then
  199. begin
  200. tmpreg := reg.reglo;
  201. reg.reglo := reg.reghi;
  202. reg.reghi := tmpreg;
  203. end;
  204. tmpref := ref;
  205. if (tmpref.base=reg.reglo) then
  206. begin
  207. tmpreg:=cg.getaddressregister(list);
  208. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  209. tmpref.base:=tmpreg;
  210. end
  211. else
  212. { this works only for the i386, thus the i386 needs to override }
  213. { this method and this method must be replaced by a more generic }
  214. { implementation FK }
  215. if (tmpref.index=reg.reglo) then
  216. begin
  217. tmpreg:=cg.getaddressregister(list);
  218. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
  219. tmpref.index:=tmpreg;
  220. end;
  221. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  222. inc(tmpref.offset,4);
  223. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  224. end;
  225. procedure tcg64f32.a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);
  226. begin
  227. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
  228. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
  229. end;
  230. procedure tcg64f32.a_load64_const_reg(list : TAsmList;value : int64;reg : tregister64);
  231. begin
  232. cg.a_load_const_reg(list,OS_32,aint(lo(value)),reg.reglo);
  233. cg.a_load_const_reg(list,OS_32,aint(hi(value)),reg.reghi);
  234. end;
  235. procedure tcg64f32.a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);
  236. var
  237. tmpreg: tregister;
  238. tmpsref: tsubsetreference;
  239. begin
  240. if (sref.bitindexreg <> NR_NO) or
  241. (sref.bitlen <> 64) then
  242. internalerror(2006082310);
  243. if (sref.startbit = 0) then
  244. begin
  245. a_load64_ref_reg(list,sref.ref,destreg);
  246. exit;
  247. end;
  248. if target_info.endian = endian_big then
  249. begin
  250. tmpreg := destreg.reglo;
  251. destreg.reglo := destreg.reghi;
  252. destreg.reghi := tmpreg;
  253. end;
  254. tmpsref:=sref;
  255. if (tmpsref.ref.base=destreg.reglo) then
  256. begin
  257. tmpreg:=cg.getaddressregister(list);
  258. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.base,tmpreg);
  259. tmpsref.ref.base:=tmpreg;
  260. end
  261. else
  262. if (tmpsref.ref.index=destreg.reglo) then
  263. begin
  264. tmpreg:=cg.getaddressregister(list);
  265. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.index,tmpreg);
  266. tmpsref.ref.index:=tmpreg;
  267. end;
  268. tmpsref.bitlen:=32;
  269. cg.a_load_subsetref_reg(list,OS_32,OS_32,tmpsref,destreg.reglo);
  270. inc(tmpsref.ref.offset,4);
  271. cg.a_load_subsetref_reg(list,OS_32,OS_32,tmpsref,destreg.reghi);
  272. end;
  273. procedure tcg64f32.a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);
  274. var
  275. tmpreg: tregister;
  276. tmpsref: tsubsetreference;
  277. begin
  278. if (sref.bitindexreg <> NR_NO) or
  279. (sref.bitlen <> 64) then
  280. internalerror(2006082311);
  281. if (sref.startbit = 0) then
  282. begin
  283. a_load64_reg_ref(list,fromreg,sref.ref);
  284. exit;
  285. end;
  286. if target_info.endian = endian_big then
  287. begin
  288. tmpreg:=fromreg.reglo;
  289. fromreg.reglo:=fromreg.reghi;
  290. fromreg.reghi:=tmpreg;
  291. end;
  292. tmpsref:=sref;
  293. tmpsref.bitlen:=32;
  294. cg.a_load_reg_subsetref(list,OS_32,OS_32,fromreg.reglo,tmpsref);
  295. inc(tmpsref.ref.offset,4);
  296. cg.a_load_reg_subsetref(list,OS_32,OS_32,fromreg.reghi,tmpsref);
  297. end;
  298. procedure tcg64f32.a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);
  299. var
  300. tmpsref: tsubsetreference;
  301. begin
  302. if (sref.bitindexreg <> NR_NO) or
  303. (sref.bitlen <> 64) then
  304. internalerror(2006082312);
  305. if target_info.endian = endian_big then
  306. swap64(a);
  307. tmpsref := sref;
  308. tmpsref.bitlen := 32;
  309. cg.a_load_const_subsetref(list,OS_32,aint(lo(a)),tmpsref);
  310. inc(tmpsref.ref.offset,4);
  311. cg.a_load_const_subsetref(list,OS_32,aint(hi(a)),tmpsref);
  312. end;
  313. procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
  314. var
  315. tmpreg64 : tregister64;
  316. begin
  317. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  318. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  319. a_load64_subsetref_reg(list,fromsref,tmpreg64);
  320. a_load64_reg_subsetref(list,tmpreg64,tosref);
  321. end;
  322. procedure tcg64f32.a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);
  323. var
  324. tmpreg64 : tregister64;
  325. begin
  326. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  327. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  328. a_load64_subsetref_reg(list,sref,tmpreg64);
  329. a_load64_reg_ref(list,tmpreg64,destref);
  330. end;
  331. procedure tcg64f32.a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);
  332. var
  333. tmpreg64 : tregister64;
  334. begin
  335. tmpreg64.reglo:=cg.getintregister(list,OS_32);
  336. tmpreg64.reghi:=cg.getintregister(list,OS_32);
  337. a_load64_ref_reg(list,fromref,tmpreg64);
  338. a_load64_reg_subsetref(list,tmpreg64,sref);
  339. end;
  340. procedure tcg64f32.a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);
  341. begin
  342. case l.loc of
  343. LOC_REFERENCE, LOC_CREFERENCE:
  344. a_load64_ref_reg(list,l.reference,reg);
  345. LOC_REGISTER,LOC_CREGISTER:
  346. a_load64_reg_reg(list,l.register64,reg);
  347. LOC_CONSTANT :
  348. a_load64_const_reg(list,l.value64,reg);
  349. LOC_SUBSETREF, LOC_CSUBSETREF:
  350. a_load64_subsetref_reg(list,l.sref,reg);
  351. else
  352. internalerror(200112292);
  353. end;
  354. end;
  355. procedure tcg64f32.a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);
  356. begin
  357. case l.loc of
  358. LOC_REGISTER,LOC_CREGISTER:
  359. a_load64_reg_ref(list,l.register64,ref);
  360. LOC_CONSTANT :
  361. a_load64_const_ref(list,l.value64,ref);
  362. LOC_SUBSETREF, LOC_CSUBSETREF:
  363. a_load64_subsetref_ref(list,l.sref,ref);
  364. else
  365. internalerror(200203288);
  366. end;
  367. end;
  368. procedure tcg64f32.a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);
  369. begin
  370. case l.loc of
  371. LOC_REFERENCE, LOC_CREFERENCE:
  372. a_load64_const_ref(list,value,l.reference);
  373. LOC_REGISTER,LOC_CREGISTER:
  374. a_load64_const_reg(list,value,l.register64);
  375. LOC_SUBSETREF, LOC_CSUBSETREF:
  376. a_load64_const_subsetref(list,value,l.sref);
  377. else
  378. internalerror(200112293);
  379. end;
  380. end;
  381. procedure tcg64f32.a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);
  382. begin
  383. case l.loc of
  384. LOC_REFERENCE, LOC_CREFERENCE:
  385. a_load64_reg_ref(list,reg,l.reference);
  386. LOC_REGISTER,LOC_CREGISTER:
  387. a_load64_reg_reg(list,reg,l.register64);
  388. LOC_SUBSETREF, LOC_CSUBSETREF:
  389. a_load64_reg_subsetref(list,reg,l.sref);
  390. else
  391. internalerror(200112293);
  392. end;
  393. end;
  394. procedure tcg64f32.a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  395. var
  396. tmpref: treference;
  397. begin
  398. if target_info.endian = endian_big then
  399. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  400. else
  401. begin
  402. tmpref := ref;
  403. inc(tmpref.offset,4);
  404. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  405. end;
  406. end;
  407. procedure tcg64f32.a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
  408. var
  409. tmpref: treference;
  410. begin
  411. if target_info.endian = endian_little then
  412. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  413. else
  414. begin
  415. tmpref := ref;
  416. inc(tmpref.offset,4);
  417. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  418. end;
  419. end;
  420. procedure tcg64f32.a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  421. var
  422. tmpref: treference;
  423. begin
  424. if target_info.endian = endian_big then
  425. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  426. else
  427. begin
  428. tmpref := ref;
  429. inc(tmpref.offset,4);
  430. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  431. end;
  432. end;
  433. procedure tcg64f32.a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
  434. var
  435. tmpref: treference;
  436. begin
  437. if target_info.endian = endian_little then
  438. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  439. else
  440. begin
  441. tmpref := ref;
  442. inc(tmpref.offset,4);
  443. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  444. end;
  445. end;
  446. procedure tcg64f32.a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  447. begin
  448. case l.loc of
  449. LOC_REFERENCE,
  450. LOC_CREFERENCE :
  451. a_load64low_ref_reg(list,l.reference,reg);
  452. LOC_REGISTER,
  453. LOC_CREGISTER :
  454. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
  455. LOC_CONSTANT :
  456. cg.a_load_const_reg(list,OS_32,aint(lo(l.value64)),reg);
  457. else
  458. internalerror(200203244);
  459. end;
  460. end;
  461. procedure tcg64f32.a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
  462. begin
  463. case l.loc of
  464. LOC_REFERENCE,
  465. LOC_CREFERENCE :
  466. a_load64high_ref_reg(list,l.reference,reg);
  467. LOC_REGISTER,
  468. LOC_CREGISTER :
  469. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
  470. LOC_CONSTANT :
  471. cg.a_load_const_reg(list,OS_32,aint(hi(l.value64)),reg);
  472. else
  473. internalerror(200203244);
  474. end;
  475. end;
  476. procedure tcg64f32.a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);
  477. begin
  478. case l.loc of
  479. LOC_REFERENCE, LOC_CREFERENCE:
  480. a_op64_const_ref(list,op,size,value,l.reference);
  481. LOC_REGISTER,LOC_CREGISTER:
  482. a_op64_const_reg(list,op,size,value,l.register64);
  483. else
  484. internalerror(200203292);
  485. end;
  486. end;
  487. procedure tcg64f32.a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);
  488. begin
  489. case l.loc of
  490. LOC_REFERENCE, LOC_CREFERENCE:
  491. a_op64_reg_ref(list,op,size,reg,l.reference);
  492. LOC_REGISTER,LOC_CREGISTER:
  493. a_op64_reg_reg(list,op,size,reg,l.register64);
  494. else
  495. internalerror(2002032422);
  496. end;
  497. end;
  498. procedure tcg64f32.a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);
  499. begin
  500. case l.loc of
  501. LOC_REFERENCE, LOC_CREFERENCE:
  502. a_op64_ref_reg(list,op,size,l.reference,reg);
  503. LOC_REGISTER,LOC_CREGISTER:
  504. a_op64_reg_reg(list,op,size,l.register64,reg);
  505. LOC_CONSTANT :
  506. a_op64_const_reg(list,op,size,l.value64,reg);
  507. else
  508. internalerror(200203242);
  509. end;
  510. end;
  511. procedure tcg64f32.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
  512. var
  513. tempreg: tregister64;
  514. begin
  515. tempreg.reghi:=cg.getintregister(list,OS_32);
  516. tempreg.reglo:=cg.getintregister(list,OS_32);
  517. a_load64_ref_reg(list,ref,tempreg);
  518. a_op64_reg_reg(list,op,size,tempreg,reg);
  519. end;
  520. procedure tcg64f32.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
  521. var
  522. tempreg: tregister64;
  523. begin
  524. tempreg.reghi:=cg.getintregister(list,OS_32);
  525. tempreg.reglo:=cg.getintregister(list,OS_32);
  526. a_load64_ref_reg(list,ref,tempreg);
  527. a_op64_reg_reg(list,op,size,reg,tempreg);
  528. a_load64_reg_ref(list,tempreg,ref);
  529. end;
  530. procedure tcg64f32.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  531. var
  532. tempreg: tregister64;
  533. begin
  534. tempreg.reghi:=cg.getintregister(list,OS_32);
  535. tempreg.reglo:=cg.getintregister(list,OS_32);
  536. a_load64_ref_reg(list,ref,tempreg);
  537. a_op64_const_reg(list,op,size,value,tempreg);
  538. a_load64_reg_ref(list,tempreg,ref);
  539. end;
  540. procedure tcg64f32.a_param64_reg(list : TAsmList;reg : tregister64;const paraloc : tcgpara);
  541. var
  542. tmplochi,tmploclo: tcgpara;
  543. begin
  544. tmploclo.init;
  545. tmplochi.init;
  546. splitparaloc64(paraloc,tmploclo,tmplochi);
  547. { Keep this order of first hi before lo to have
  548. the correct push order for i386 }
  549. cg.a_param_reg(list,OS_32,reg.reghi,tmplochi);
  550. cg.a_param_reg(list,OS_32,reg.reglo,tmploclo);
  551. tmploclo.done;
  552. tmplochi.done;
  553. end;
  554. procedure tcg64f32.a_param64_const(list : TAsmList;value : int64;const paraloc : tcgpara);
  555. var
  556. tmplochi,tmploclo: tcgpara;
  557. begin
  558. tmploclo.init;
  559. tmplochi.init;
  560. splitparaloc64(paraloc,tmploclo,tmplochi);
  561. { Keep this order of first hi before lo to have
  562. the correct push order for i386 }
  563. cg.a_param_const(list,OS_32,aint(hi(value)),tmplochi);
  564. cg.a_param_const(list,OS_32,aint(lo(value)),tmploclo);
  565. tmploclo.done;
  566. tmplochi.done;
  567. end;
  568. procedure tcg64f32.a_param64_ref(list : TAsmList;const r : treference;const paraloc : tcgpara);
  569. var
  570. tmprefhi,tmpreflo : treference;
  571. tmploclo,tmplochi : tcgpara;
  572. begin
  573. tmploclo.init;
  574. tmplochi.init;
  575. splitparaloc64(paraloc,tmploclo,tmplochi);
  576. tmprefhi:=r;
  577. tmpreflo:=r;
  578. if target_info.endian=endian_big then
  579. inc(tmpreflo.offset,4)
  580. else
  581. inc(tmprefhi.offset,4);
  582. { Keep this order of first hi before lo to have
  583. the correct push order for i386 }
  584. cg.a_param_ref(list,OS_32,tmprefhi,tmplochi);
  585. cg.a_param_ref(list,OS_32,tmpreflo,tmploclo);
  586. tmploclo.done;
  587. tmplochi.done;
  588. end;
  589. procedure tcg64f32.a_param64_loc(list : TAsmList;const l:tlocation;const paraloc : tcgpara);
  590. begin
  591. case l.loc of
  592. LOC_REGISTER,
  593. LOC_CREGISTER :
  594. a_param64_reg(list,l.register64,paraloc);
  595. LOC_CONSTANT :
  596. a_param64_const(list,l.value64,paraloc);
  597. LOC_CREFERENCE,
  598. LOC_REFERENCE :
  599. a_param64_ref(list,l.reference,paraloc);
  600. else
  601. internalerror(200203287);
  602. end;
  603. end;
  604. procedure tcg64f32.g_rangecheck64(list : TAsmList;const l:tlocation;fromdef,todef:tdef);
  605. var
  606. neglabel,
  607. poslabel,
  608. endlabel: tasmlabel;
  609. hreg : tregister;
  610. hdef : torddef;
  611. opsize : tcgsize;
  612. from_signed,to_signed: boolean;
  613. temploc : tlocation;
  614. begin
  615. from_signed := is_signed(fromdef);
  616. to_signed := is_signed(todef);
  617. if not is_64bit(todef) then
  618. begin
  619. { get the high dword in a register }
  620. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  621. begin
  622. hreg := l.register64.reghi;
  623. end
  624. else
  625. begin
  626. hreg:=cg.getintregister(list,OS_32);
  627. a_load64high_ref_reg(list,l.reference,hreg);
  628. end;
  629. current_asmdata.getjumplabel(poslabel);
  630. { check high dword, must be 0 (for positive numbers) }
  631. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  632. { It can also be $ffffffff, but only for negative numbers }
  633. if from_signed and to_signed then
  634. begin
  635. current_asmdata.getjumplabel(neglabel);
  636. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  637. end;
  638. { For all other values we have a range check error }
  639. cg.a_call_name(list,'FPC_RANGEERROR',false);
  640. { if the high dword = 0, the low dword can be considered a }
  641. { simple cardinal }
  642. cg.a_label(list,poslabel);
  643. hdef:=torddef.create(u32bit,0,$ffffffff);
  644. location_copy(temploc,l);
  645. temploc.size:=OS_32;
  646. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  647. (target_info.endian = endian_big) then
  648. begin
  649. inc(temploc.reference.offset,4);
  650. temploc.reference.alignment:=newalignment(temploc.reference.alignment,4);
  651. end;
  652. cg.g_rangecheck(list,temploc,hdef,todef);
  653. hdef.owner.deletedef(hdef);
  654. if from_signed and to_signed then
  655. begin
  656. current_asmdata.getjumplabel(endlabel);
  657. cg.a_jmp_always(list,endlabel);
  658. { if the high dword = $ffffffff, then the low dword (when }
  659. { considered as a longint) must be < 0 }
  660. cg.a_label(list,neglabel);
  661. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  662. begin
  663. hreg := l.register64.reglo;
  664. end
  665. else
  666. begin
  667. hreg:=cg.getintregister(list,OS_32);
  668. a_load64low_ref_reg(list,l.reference,hreg);
  669. end;
  670. { get a new neglabel (JM) }
  671. current_asmdata.getjumplabel(neglabel);
  672. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  673. cg.a_call_name(list,'FPC_RANGEERROR',false);
  674. { if we get here, the 64bit value lies between }
  675. { longint($80000000) and -1 (JM) }
  676. cg.a_label(list,neglabel);
  677. hdef:=torddef.create(s32bit,int64(longint($80000000)),int64(-1));
  678. location_copy(temploc,l);
  679. temploc.size:=OS_32;
  680. cg.g_rangecheck(list,temploc,hdef,todef);
  681. hdef.owner.deletedef(hdef);
  682. cg.a_label(list,endlabel);
  683. end;
  684. end
  685. else
  686. { todef = 64bit int }
  687. { no 64bit subranges supported, so only a small check is necessary }
  688. { if both are signed or both are unsigned, no problem! }
  689. if (from_signed xor to_signed) and
  690. { also not if the fromdef is unsigned and < 64bit, since that will }
  691. { always fit in a 64bit int (todef is 64bit) }
  692. (from_signed or
  693. (torddef(fromdef).ordtype = u64bit)) then
  694. begin
  695. { in all cases, there is only a problem if the higest bit is set }
  696. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  697. begin
  698. if is_64bit(fromdef) then
  699. begin
  700. hreg := l.register64.reghi;
  701. opsize := OS_32;
  702. end
  703. else
  704. begin
  705. hreg := l.register;
  706. opsize := def_cgsize(fromdef);
  707. end;
  708. end
  709. else
  710. begin
  711. hreg:=cg.getintregister(list,OS_32);
  712. opsize:=OS_32;
  713. if l.size in [OS_64,OS_S64] then
  714. a_load64high_ref_reg(list,l.reference,hreg)
  715. else
  716. cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
  717. end;
  718. current_asmdata.getjumplabel(poslabel);
  719. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  720. cg.a_call_name(list,'FPC_RANGEERROR',false);
  721. cg.a_label(list,poslabel);
  722. end;
  723. end;
  724. function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
  725. var
  726. lowvalue, highvalue : longint;
  727. hreg: tregister;
  728. begin
  729. lowvalue := longint(a);
  730. highvalue:= longint(a shr 32);
  731. { assume it will be optimized out }
  732. optimize64_op_const_reg := true;
  733. case op of
  734. OP_ADD:
  735. begin
  736. if a = 0 then
  737. exit;
  738. end;
  739. OP_AND:
  740. begin
  741. if lowvalue <> -1 then
  742. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  743. if highvalue <> -1 then
  744. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  745. { already emitted correctly }
  746. exit;
  747. end;
  748. OP_OR:
  749. begin
  750. if lowvalue <> 0 then
  751. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  752. if highvalue <> 0 then
  753. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  754. { already emitted correctly }
  755. exit;
  756. end;
  757. OP_SUB:
  758. begin
  759. if a = 0 then
  760. exit;
  761. end;
  762. OP_XOR:
  763. begin
  764. end;
  765. OP_SHL:
  766. begin
  767. if a = 0 then
  768. exit;
  769. { simply clear low-register
  770. and shift the rest and swap
  771. registers.
  772. }
  773. if (a > 31) then
  774. begin
  775. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  776. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  777. { swap the registers }
  778. hreg := reg.reghi;
  779. reg.reghi := reg.reglo;
  780. reg.reglo := hreg;
  781. exit;
  782. end;
  783. end;
  784. OP_SHR:
  785. begin
  786. if a = 0 then exit;
  787. { simply clear high-register
  788. and shift the rest and swap
  789. registers.
  790. }
  791. if (a > 31) then
  792. begin
  793. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  794. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  795. { swap the registers }
  796. hreg := reg.reghi;
  797. reg.reghi := reg.reglo;
  798. reg.reglo := hreg;
  799. exit;
  800. end;
  801. end;
  802. OP_IMUL,OP_MUL:
  803. begin
  804. if a = 1 then exit;
  805. end;
  806. OP_IDIV,OP_DIV:
  807. begin
  808. if a = 1 then exit;
  809. end;
  810. else
  811. internalerror(20020817);
  812. end;
  813. optimize64_op_const_reg := false;
  814. end;
  815. end.