cg64f32.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Member of the Free Pascal development team
  5. This unit implements the code generation for 64 bit int
  6. arithmethics on 32 bit processors
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. {# This unit implements the code generation for 64 bit int arithmethics on
  21. 32 bit processors.
  22. }
  23. unit cg64f32;
  24. {$i fpcdefs.inc}
  25. interface
  26. uses
  27. aasmbase,aasmtai,aasmcpu,
  28. cpuinfo,cpubase,cpupara,
  29. cgbase,cgobj,parabase,
  30. node,symtype
  31. ;
  32. type
  33. {# Defines all the methods required on 32-bit processors
  34. to handle 64-bit integers.
  35. }
  36. tcg64f32 = class(tcg64)
  37. procedure a_load64_const_ref(list : taasmoutput;value : int64;const ref : treference);override;
  38. procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);override;
  39. procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);override;
  40. procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);override;
  41. procedure a_load64_const_reg(list : taasmoutput;value: int64;reg : tregister64);override;
  42. procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);override;
  43. procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);override;
  44. procedure a_load64_const_loc(list : taasmoutput;value : int64;const l : tlocation);override;
  45. procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);override;
  46. procedure a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);override;
  47. procedure a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);override;
  48. procedure a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);override;
  49. procedure a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);override;
  50. procedure a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);override;
  51. procedure a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);override;
  52. procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);override;
  53. procedure a_op64_reg_ref(list : taasmoutput;op:TOpCG;reg : tregister64; const ref: treference);override;
  54. procedure a_op64_const_loc(list : taasmoutput;op:TOpCG;value : int64;const l: tlocation);override;
  55. procedure a_op64_reg_loc(list : taasmoutput;op:TOpCG;reg : tregister64;const l : tlocation);override;
  56. procedure a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reg : tregister64);override;
  57. procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);override;
  58. procedure a_param64_reg(list : taasmoutput;reg : tregister64;const paraloc : tcgpara);override;
  59. procedure a_param64_const(list : taasmoutput;value : int64;const paraloc : tcgpara);override;
  60. procedure a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);override;
  61. procedure a_param64_loc(list : taasmoutput;const l : tlocation;const paraloc : tcgpara);override;
  62. {# This routine tries to optimize the a_op64_const_reg operation, by
  63. removing superfluous opcodes. Returns TRUE if normal processing
  64. must continue in op64_const_reg, otherwise, everything is processed
  65. entirely in this routine, by emitting the appropriate 32-bit opcodes.
  66. }
  67. function optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
  68. procedure g_rangecheck64(list: taasmoutput; const l:tlocation;fromdef,todef: tdef); override;
  69. end;
  70. {# Creates a tregister64 record from 2 32 Bit registers. }
  71. function joinreg64(reglo,reghi : tregister) : tregister64;
  72. implementation
  73. uses
  74. globtype,systems,
  75. verbose,
  76. symbase,symconst,symdef,defutil,paramgr;
  77. {****************************************************************************
  78. Helpers
  79. ****************************************************************************}
  80. function joinreg64(reglo,reghi : tregister) : tregister64;
  81. begin
  82. result.reglo:=reglo;
  83. result.reghi:=reghi;
  84. end;
  85. procedure swap64(var q : int64);
  86. begin
  87. q:=(int64(lo(q)) shl 32) or hi(q);
  88. end;
  89. procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
  90. var
  91. paraloclo,
  92. paralochi : pcgparalocation;
  93. begin
  94. if not(cgpara.size in [OS_64,OS_S64]) then
  95. internalerror(200408231);
  96. if not assigned(cgpara.location) then
  97. internalerror(200408201);
  98. { init lo/hi para }
  99. cgparahi.reset;
  100. if cgpara.size=OS_S64 then
  101. cgparahi.size:=OS_S32
  102. else
  103. cgparahi.size:=OS_32;
  104. cgparahi.alignment:=cgpara.alignment;
  105. paralochi:=cgparahi.add_location;
  106. cgparalo.reset;
  107. cgparalo.size:=OS_32;
  108. cgparalo.alignment:=cgpara.alignment;
  109. paraloclo:=cgparalo.add_location;
  110. { 2 parameter fields? }
  111. if assigned(cgpara.location^.next) then
  112. begin
  113. if target_info.endian = endian_big then
  114. begin
  115. { low is in second location }
  116. move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
  117. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  118. end
  119. else
  120. begin
  121. { low is in first location }
  122. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  123. move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
  124. end;
  125. end
  126. else
  127. begin
  128. { single parameter, this can only be in memory }
  129. if cgpara.location^.loc<>LOC_REFERENCE then
  130. internalerror(200408282);
  131. move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
  132. move(cgpara.location^,paralochi^,sizeof(paralochi^));
  133. { for big endian low is at +4, for little endian high }
  134. if target_info.endian = endian_big then
  135. inc(cgparalo.location^.reference.offset,tcgsize2size[cgparahi.size])
  136. else
  137. inc(cgparahi.location^.reference.offset,tcgsize2size[cgparalo.size]);
  138. end;
  139. { fix size }
  140. paraloclo^.size:=cgparalo.size;
  141. paraloclo^.next:=nil;
  142. paralochi^.size:=cgparahi.size;
  143. paralochi^.next:=nil;
  144. end;
  145. {****************************************************************************
  146. TCG64F32
  147. ****************************************************************************}
  148. procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);
  149. var
  150. tmpreg: tregister;
  151. tmpref: treference;
  152. begin
  153. if target_info.endian = endian_big then
  154. begin
  155. tmpreg:=reg.reglo;
  156. reg.reglo:=reg.reghi;
  157. reg.reghi:=tmpreg;
  158. end;
  159. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
  160. tmpref := ref;
  161. inc(tmpref.offset,4);
  162. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  163. end;
  164. procedure tcg64f32.a_load64_const_ref(list : taasmoutput;value : int64;const ref : treference);
  165. var
  166. tmpref: treference;
  167. begin
  168. if target_info.endian = endian_big then
  169. swap64(value);
  170. cg.a_load_const_ref(list,OS_32,aint(lo(value)),ref);
  171. tmpref := ref;
  172. inc(tmpref.offset,4);
  173. cg.a_load_const_ref(list,OS_32,aint(hi(value)),tmpref);
  174. end;
  175. procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);
  176. var
  177. tmpreg: tregister;
  178. tmpref: treference;
  179. begin
  180. if target_info.endian = endian_big then
  181. begin
  182. tmpreg := reg.reglo;
  183. reg.reglo := reg.reghi;
  184. reg.reghi := tmpreg;
  185. end;
  186. tmpref := ref;
  187. if (tmpref.base=reg.reglo) then
  188. begin
  189. tmpreg:=cg.getaddressregister(list);
  190. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  191. tmpref.base:=tmpreg;
  192. end
  193. else
  194. { this works only for the i386, thus the i386 needs to override }
  195. { this method and this method must be replaced by a more generic }
  196. { implementation FK }
  197. if (tmpref.index=reg.reglo) then
  198. begin
  199. tmpreg:=cg.getaddressregister(list);
  200. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
  201. tmpref.index:=tmpreg;
  202. end;
  203. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  204. inc(tmpref.offset,4);
  205. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  206. end;
  207. procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);
  208. begin
  209. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
  210. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
  211. end;
  212. procedure tcg64f32.a_load64_const_reg(list : taasmoutput;value : int64;reg : tregister64);
  213. begin
  214. cg.a_load_const_reg(list,OS_32,aint(lo(value)),reg.reglo);
  215. cg.a_load_const_reg(list,OS_32,aint(hi(value)),reg.reghi);
  216. end;
  217. procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);
  218. begin
  219. case l.loc of
  220. LOC_REFERENCE, LOC_CREFERENCE:
  221. a_load64_ref_reg(list,l.reference,reg);
  222. LOC_REGISTER,LOC_CREGISTER:
  223. a_load64_reg_reg(list,l.register64,reg);
  224. LOC_CONSTANT :
  225. a_load64_const_reg(list,l.value64,reg);
  226. else
  227. internalerror(200112292);
  228. end;
  229. end;
  230. procedure tcg64f32.a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);
  231. begin
  232. case l.loc of
  233. LOC_REGISTER,LOC_CREGISTER:
  234. a_load64_reg_ref(list,l.register64,ref);
  235. LOC_CONSTANT :
  236. a_load64_const_ref(list,l.value64,ref);
  237. else
  238. internalerror(200203288);
  239. end;
  240. end;
  241. procedure tcg64f32.a_load64_const_loc(list : taasmoutput;value : int64;const l : tlocation);
  242. begin
  243. case l.loc of
  244. LOC_REFERENCE, LOC_CREFERENCE:
  245. a_load64_const_ref(list,value,l.reference);
  246. LOC_REGISTER,LOC_CREGISTER:
  247. a_load64_const_reg(list,value,l.register64);
  248. else
  249. internalerror(200112293);
  250. end;
  251. end;
  252. procedure tcg64f32.a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);
  253. begin
  254. case l.loc of
  255. LOC_REFERENCE, LOC_CREFERENCE:
  256. a_load64_reg_ref(list,reg,l.reference);
  257. LOC_REGISTER,LOC_CREGISTER:
  258. a_load64_reg_reg(list,reg,l.register64);
  259. else
  260. internalerror(200112293);
  261. end;
  262. end;
  263. procedure tcg64f32.a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
  264. var
  265. tmpref: treference;
  266. begin
  267. if target_info.endian = endian_big then
  268. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  269. else
  270. begin
  271. tmpref := ref;
  272. inc(tmpref.offset,4);
  273. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  274. end;
  275. end;
  276. procedure tcg64f32.a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
  277. var
  278. tmpref: treference;
  279. begin
  280. if target_info.endian = endian_little then
  281. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  282. else
  283. begin
  284. tmpref := ref;
  285. inc(tmpref.offset,4);
  286. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  287. end;
  288. end;
  289. procedure tcg64f32.a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
  290. var
  291. tmpref: treference;
  292. begin
  293. if target_info.endian = endian_big then
  294. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  295. else
  296. begin
  297. tmpref := ref;
  298. inc(tmpref.offset,4);
  299. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  300. end;
  301. end;
  302. procedure tcg64f32.a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
  303. var
  304. tmpref: treference;
  305. begin
  306. if target_info.endian = endian_little then
  307. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  308. else
  309. begin
  310. tmpref := ref;
  311. inc(tmpref.offset,4);
  312. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  313. end;
  314. end;
  315. procedure tcg64f32.a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  316. begin
  317. case l.loc of
  318. LOC_REFERENCE,
  319. LOC_CREFERENCE :
  320. a_load64low_ref_reg(list,l.reference,reg);
  321. LOC_REGISTER :
  322. cg.a_load_reg_reg(list,OS_32,OS_32,l.registerlow,reg);
  323. LOC_CONSTANT :
  324. cg.a_load_const_reg(list,OS_32,aint(lo(l.value64)),reg);
  325. else
  326. internalerror(200203244);
  327. end;
  328. end;
  329. procedure tcg64f32.a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  330. begin
  331. case l.loc of
  332. LOC_REFERENCE,
  333. LOC_CREFERENCE :
  334. a_load64high_ref_reg(list,l.reference,reg);
  335. LOC_REGISTER :
  336. cg.a_load_reg_reg(list,OS_32,OS_32,l.registerhigh,reg);
  337. LOC_CONSTANT :
  338. cg.a_load_const_reg(list,OS_32,hi(l.value64),reg);
  339. else
  340. internalerror(200203244);
  341. end;
  342. end;
  343. procedure tcg64f32.a_op64_const_loc(list : taasmoutput;op:TOpCG;value : int64;const l: tlocation);
  344. begin
  345. case l.loc of
  346. LOC_REFERENCE, LOC_CREFERENCE:
  347. a_op64_const_ref(list,op,value,l.reference);
  348. LOC_REGISTER,LOC_CREGISTER:
  349. a_op64_const_reg(list,op,value,l.register64);
  350. else
  351. internalerror(200203292);
  352. end;
  353. end;
  354. procedure tcg64f32.a_op64_reg_loc(list : taasmoutput;op:TOpCG;reg : tregister64;const l : tlocation);
  355. begin
  356. case l.loc of
  357. LOC_REFERENCE, LOC_CREFERENCE:
  358. a_op64_reg_ref(list,op,reg,l.reference);
  359. LOC_REGISTER,LOC_CREGISTER:
  360. a_op64_reg_reg(list,op,reg,l.register64);
  361. else
  362. internalerror(2002032422);
  363. end;
  364. end;
  365. procedure tcg64f32.a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reg : tregister64);
  366. begin
  367. case l.loc of
  368. LOC_REFERENCE, LOC_CREFERENCE:
  369. a_op64_ref_reg(list,op,l.reference,reg);
  370. LOC_REGISTER,LOC_CREGISTER:
  371. a_op64_reg_reg(list,op,l.register64,reg);
  372. LOC_CONSTANT :
  373. a_op64_const_reg(list,op,l.value64,reg);
  374. else
  375. internalerror(200203242);
  376. end;
  377. end;
  378. procedure tcg64f32.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);
  379. var
  380. tempreg: tregister64;
  381. begin
  382. tempreg.reghi:=cg.getintregister(list,OS_32);
  383. tempreg.reglo:=cg.getintregister(list,OS_32);
  384. a_load64_ref_reg(list,ref,tempreg);
  385. a_op64_reg_reg(list,op,tempreg,reg);
  386. end;
  387. procedure tcg64f32.a_op64_reg_ref(list : taasmoutput;op:TOpCG;reg : tregister64; const ref: treference);
  388. var
  389. tempreg: tregister64;
  390. begin
  391. tempreg.reghi:=cg.getintregister(list,OS_32);
  392. tempreg.reglo:=cg.getintregister(list,OS_32);
  393. a_load64_ref_reg(list,ref,tempreg);
  394. a_op64_reg_reg(list,op,reg,tempreg);
  395. a_load64_reg_ref(list,tempreg,ref);
  396. end;
  397. procedure tcg64f32.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);
  398. var
  399. tempreg: tregister64;
  400. begin
  401. tempreg.reghi:=cg.getintregister(list,OS_32);
  402. tempreg.reglo:=cg.getintregister(list,OS_32);
  403. a_load64_ref_reg(list,ref,tempreg);
  404. a_op64_const_reg(list,op,value,tempreg);
  405. a_load64_reg_ref(list,tempreg,ref);
  406. end;
  407. procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const paraloc : tcgpara);
  408. var
  409. tmplochi,tmploclo: tcgpara;
  410. begin
  411. tmploclo.init;
  412. tmplochi.init;
  413. splitparaloc64(paraloc,tmploclo,tmplochi);
  414. cg.a_param_reg(list,OS_32,reg.reghi,tmplochi);
  415. cg.a_param_reg(list,OS_32,reg.reglo,tmploclo);
  416. tmploclo.done;
  417. tmplochi.done;
  418. end;
  419. procedure tcg64f32.a_param64_const(list : taasmoutput;value : int64;const paraloc : tcgpara);
  420. var
  421. tmplochi,tmploclo: tcgpara;
  422. begin
  423. tmploclo.init;
  424. tmplochi.init;
  425. splitparaloc64(paraloc,tmploclo,tmplochi);
  426. cg.a_param_const(list,OS_32,aint(hi(value)),tmplochi);
  427. cg.a_param_const(list,OS_32,aint(lo(value)),tmploclo);
  428. tmploclo.done;
  429. tmplochi.done;
  430. end;
  431. procedure tcg64f32.a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);
  432. var
  433. tmprefhi,tmpreflo : treference;
  434. tmploclo,tmplochi : tcgpara;
  435. begin
  436. tmploclo.init;
  437. tmplochi.init;
  438. splitparaloc64(paraloc,tmploclo,tmplochi);
  439. tmprefhi:=r;
  440. tmpreflo:=r;
  441. if target_info.endian=endian_big then
  442. inc(tmpreflo.offset,4)
  443. else
  444. inc(tmprefhi.offset,4);
  445. cg.a_param_ref(list,OS_32,tmprefhi,tmplochi);
  446. cg.a_param_ref(list,OS_32,tmpreflo,tmploclo);
  447. tmploclo.done;
  448. tmplochi.done;
  449. end;
  450. procedure tcg64f32.a_param64_loc(list : taasmoutput;const l:tlocation;const paraloc : tcgpara);
  451. begin
  452. case l.loc of
  453. LOC_REGISTER,
  454. LOC_CREGISTER :
  455. a_param64_reg(list,l.register64,paraloc);
  456. LOC_CONSTANT :
  457. a_param64_const(list,l.value64,paraloc);
  458. LOC_CREFERENCE,
  459. LOC_REFERENCE :
  460. a_param64_ref(list,l.reference,paraloc);
  461. else
  462. internalerror(200203287);
  463. end;
  464. end;
  465. procedure tcg64f32.g_rangecheck64(list : taasmoutput;const l:tlocation;fromdef,todef:tdef);
  466. var
  467. neglabel,
  468. poslabel,
  469. endlabel: tasmlabel;
  470. hreg : tregister;
  471. hdef : torddef;
  472. opsize : tcgsize;
  473. oldregisterdef: boolean;
  474. from_signed,to_signed: boolean;
  475. temploc : tlocation;
  476. begin
  477. from_signed := is_signed(fromdef);
  478. to_signed := is_signed(todef);
  479. if not is_64bit(todef) then
  480. begin
  481. oldregisterdef := registerdef;
  482. registerdef := false;
  483. { get the high dword in a register }
  484. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  485. begin
  486. hreg := l.registerhigh;
  487. end
  488. else
  489. begin
  490. hreg:=cg.getintregister(list,OS_32);
  491. a_load64high_ref_reg(list,l.reference,hreg);
  492. end;
  493. objectlibrary.getlabel(poslabel);
  494. { check high dword, must be 0 (for positive numbers) }
  495. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  496. { It can also be $ffffffff, but only for negative numbers }
  497. if from_signed and to_signed then
  498. begin
  499. objectlibrary.getlabel(neglabel);
  500. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  501. end;
  502. { For all other values we have a range check error }
  503. cg.a_call_name(list,'FPC_RANGEERROR');
  504. { if the high dword = 0, the low dword can be considered a }
  505. { simple cardinal }
  506. cg.a_label(list,poslabel);
  507. hdef:=torddef.create(u32bit,0,$ffffffff);
  508. location_copy(temploc,l);
  509. temploc.size:=OS_32;
  510. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  511. (target_info.endian = endian_big) then
  512. inc(temploc.reference.offset,4);
  513. cg.g_rangecheck(list,temploc,hdef,todef);
  514. hdef.free;
  515. if from_signed and to_signed then
  516. begin
  517. objectlibrary.getlabel(endlabel);
  518. cg.a_jmp_always(list,endlabel);
  519. { if the high dword = $ffffffff, then the low dword (when }
  520. { considered as a longint) must be < 0 }
  521. cg.a_label(list,neglabel);
  522. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  523. begin
  524. hreg := l.registerlow;
  525. end
  526. else
  527. begin
  528. hreg:=cg.getintregister(list,OS_32);
  529. a_load64low_ref_reg(list,l.reference,hreg);
  530. end;
  531. { get a new neglabel (JM) }
  532. objectlibrary.getlabel(neglabel);
  533. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  534. cg.a_call_name(list,'FPC_RANGEERROR');
  535. { if we get here, the 64bit value lies between }
  536. { longint($80000000) and -1 (JM) }
  537. cg.a_label(list,neglabel);
  538. hdef:=torddef.create(s32bit,longint($80000000),-1);
  539. location_copy(temploc,l);
  540. temploc.size:=OS_32;
  541. cg.g_rangecheck(list,temploc,hdef,todef);
  542. hdef.free;
  543. cg.a_label(list,endlabel);
  544. end;
  545. registerdef := oldregisterdef;
  546. end
  547. else
  548. { todef = 64bit int }
  549. { no 64bit subranges supported, so only a small check is necessary }
  550. { if both are signed or both are unsigned, no problem! }
  551. if (from_signed xor to_signed) and
  552. { also not if the fromdef is unsigned and < 64bit, since that will }
  553. { always fit in a 64bit int (todef is 64bit) }
  554. (from_signed or
  555. (torddef(fromdef).typ = u64bit)) then
  556. begin
  557. { in all cases, there is only a problem if the higest bit is set }
  558. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  559. begin
  560. if is_64bit(fromdef) then
  561. begin
  562. hreg := l.registerhigh;
  563. opsize := OS_32;
  564. end
  565. else
  566. begin
  567. hreg := l.register;
  568. opsize := def_cgsize(fromdef);
  569. end;
  570. end
  571. else
  572. begin
  573. hreg:=cg.getintregister(list,OS_32);
  574. opsize := def_cgsize(fromdef);
  575. if opsize in [OS_64,OS_S64] then
  576. a_load64high_ref_reg(list,l.reference,hreg)
  577. else
  578. cg.a_load_ref_reg(list,opsize,OS_32,l.reference,hreg);
  579. end;
  580. objectlibrary.getlabel(poslabel);
  581. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  582. cg.a_call_name(list,'FPC_RANGEERROR');
  583. cg.a_label(list,poslabel);
  584. end;
  585. end;
  586. function tcg64f32.optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : int64; var reg: tregister64): boolean;
  587. var
  588. lowvalue, highvalue : longint;
  589. hreg: tregister;
  590. begin
  591. lowvalue := longint(a);
  592. highvalue:= longint(a shr 32);
  593. { assume it will be optimized out }
  594. optimize64_op_const_reg := true;
  595. case op of
  596. OP_ADD:
  597. begin
  598. if a = 0 then
  599. exit;
  600. end;
  601. OP_AND:
  602. begin
  603. if lowvalue <> -1 then
  604. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  605. if highvalue <> -1 then
  606. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  607. { already emitted correctly }
  608. exit;
  609. end;
  610. OP_OR:
  611. begin
  612. if lowvalue <> 0 then
  613. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  614. if highvalue <> 0 then
  615. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  616. { already emitted correctly }
  617. exit;
  618. end;
  619. OP_SUB:
  620. begin
  621. if a = 0 then
  622. exit;
  623. end;
  624. OP_XOR:
  625. begin
  626. end;
  627. OP_SHL:
  628. begin
  629. if a = 0 then
  630. exit;
  631. { simply clear low-register
  632. and shift the rest and swap
  633. registers.
  634. }
  635. if (a > 31) then
  636. begin
  637. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  638. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  639. { swap the registers }
  640. hreg := reg.reghi;
  641. reg.reghi := reg.reglo;
  642. reg.reglo := hreg;
  643. exit;
  644. end;
  645. end;
  646. OP_SHR:
  647. begin
  648. if a = 0 then exit;
  649. { simply clear high-register
  650. and shift the rest and swap
  651. registers.
  652. }
  653. if (a > 31) then
  654. begin
  655. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  656. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  657. { swap the registers }
  658. hreg := reg.reghi;
  659. reg.reghi := reg.reglo;
  660. reg.reglo := hreg;
  661. exit;
  662. end;
  663. end;
  664. OP_IMUL,OP_MUL:
  665. begin
  666. if a = 1 then exit;
  667. end;
  668. OP_IDIV,OP_DIV:
  669. begin
  670. if a = 1 then exit;
  671. end;
  672. else
  673. internalerror(20020817);
  674. end;
  675. optimize64_op_const_reg := false;
  676. end;
  677. end.
  678. {
  679. $Log$
  680. Revision 1.64 2004-10-15 09:14:16 mazen
  681. - remove $IFDEF DELPHI and related code
  682. - remove $IFDEF FPCPROCVAR and related code
  683. Revision 1.63 2004/09/25 14:23:54 peter
  684. * ungetregister is now only used for cpuregisters, renamed to
  685. ungetcpuregister
  686. * renamed (get|unget)explicitregister(s) to ..cpuregister
  687. * removed location-release/reference_release
  688. Revision 1.62 2004/09/21 17:25:12 peter
  689. * paraloc branch merged
  690. Revision 1.61.4.2 2004/09/20 20:46:34 peter
  691. * register allocation optimized for 64bit loading of parameters
  692. and return values
  693. Revision 1.61.4.1 2004/08/31 20:43:06 peter
  694. * paraloc patch
  695. Revision 1.61 2004/06/20 08:55:28 florian
  696. * logs truncated
  697. Revision 1.60 2004/06/18 15:16:46 peter
  698. * remove obsolete cardinal() typecasts
  699. Revision 1.59 2004/06/17 16:55:46 peter
  700. * powerpc compiles again
  701. Revision 1.58 2004/06/16 20:07:07 florian
  702. * dwarf branch merged
  703. Revision 1.57.2.5 2004/06/13 10:51:16 florian
  704. * fixed several register allocator problems (sparc/arm)
  705. Revision 1.57.2.4 2004/06/12 17:01:01 florian
  706. * fixed compilation of arm compiler
  707. }