cg64f32.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  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. cpubase,cpupara,
  29. cgbase,cgobj,parabase,cgutils,
  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. LOC_CREGISTER :
  323. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
  324. LOC_CONSTANT :
  325. cg.a_load_const_reg(list,OS_32,aint(lo(l.value64)),reg);
  326. else
  327. internalerror(200203244);
  328. end;
  329. end;
  330. procedure tcg64f32.a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  331. begin
  332. case l.loc of
  333. LOC_REFERENCE,
  334. LOC_CREFERENCE :
  335. a_load64high_ref_reg(list,l.reference,reg);
  336. LOC_REGISTER,
  337. LOC_CREGISTER :
  338. cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
  339. LOC_CONSTANT :
  340. cg.a_load_const_reg(list,OS_32,hi(l.value64),reg);
  341. else
  342. internalerror(200203244);
  343. end;
  344. end;
  345. procedure tcg64f32.a_op64_const_loc(list : taasmoutput;op:TOpCG;value : int64;const l: tlocation);
  346. begin
  347. case l.loc of
  348. LOC_REFERENCE, LOC_CREFERENCE:
  349. a_op64_const_ref(list,op,value,l.reference);
  350. LOC_REGISTER,LOC_CREGISTER:
  351. a_op64_const_reg(list,op,value,l.register64);
  352. else
  353. internalerror(200203292);
  354. end;
  355. end;
  356. procedure tcg64f32.a_op64_reg_loc(list : taasmoutput;op:TOpCG;reg : tregister64;const l : tlocation);
  357. begin
  358. case l.loc of
  359. LOC_REFERENCE, LOC_CREFERENCE:
  360. a_op64_reg_ref(list,op,reg,l.reference);
  361. LOC_REGISTER,LOC_CREGISTER:
  362. a_op64_reg_reg(list,op,reg,l.register64);
  363. else
  364. internalerror(2002032422);
  365. end;
  366. end;
  367. procedure tcg64f32.a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reg : tregister64);
  368. begin
  369. case l.loc of
  370. LOC_REFERENCE, LOC_CREFERENCE:
  371. a_op64_ref_reg(list,op,l.reference,reg);
  372. LOC_REGISTER,LOC_CREGISTER:
  373. a_op64_reg_reg(list,op,l.register64,reg);
  374. LOC_CONSTANT :
  375. a_op64_const_reg(list,op,l.value64,reg);
  376. else
  377. internalerror(200203242);
  378. end;
  379. end;
  380. procedure tcg64f32.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);
  381. var
  382. tempreg: tregister64;
  383. begin
  384. tempreg.reghi:=cg.getintregister(list,OS_32);
  385. tempreg.reglo:=cg.getintregister(list,OS_32);
  386. a_load64_ref_reg(list,ref,tempreg);
  387. a_op64_reg_reg(list,op,tempreg,reg);
  388. end;
  389. procedure tcg64f32.a_op64_reg_ref(list : taasmoutput;op:TOpCG;reg : tregister64; const ref: treference);
  390. var
  391. tempreg: tregister64;
  392. begin
  393. tempreg.reghi:=cg.getintregister(list,OS_32);
  394. tempreg.reglo:=cg.getintregister(list,OS_32);
  395. a_load64_ref_reg(list,ref,tempreg);
  396. a_op64_reg_reg(list,op,reg,tempreg);
  397. a_load64_reg_ref(list,tempreg,ref);
  398. end;
  399. procedure tcg64f32.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);
  400. var
  401. tempreg: tregister64;
  402. begin
  403. tempreg.reghi:=cg.getintregister(list,OS_32);
  404. tempreg.reglo:=cg.getintregister(list,OS_32);
  405. a_load64_ref_reg(list,ref,tempreg);
  406. a_op64_const_reg(list,op,value,tempreg);
  407. a_load64_reg_ref(list,tempreg,ref);
  408. end;
  409. procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const paraloc : tcgpara);
  410. var
  411. tmplochi,tmploclo: tcgpara;
  412. begin
  413. tmploclo.init;
  414. tmplochi.init;
  415. splitparaloc64(paraloc,tmploclo,tmplochi);
  416. cg.a_param_reg(list,OS_32,reg.reghi,tmplochi);
  417. cg.a_param_reg(list,OS_32,reg.reglo,tmploclo);
  418. tmploclo.done;
  419. tmplochi.done;
  420. end;
  421. procedure tcg64f32.a_param64_const(list : taasmoutput;value : int64;const paraloc : tcgpara);
  422. var
  423. tmplochi,tmploclo: tcgpara;
  424. begin
  425. tmploclo.init;
  426. tmplochi.init;
  427. splitparaloc64(paraloc,tmploclo,tmplochi);
  428. cg.a_param_const(list,OS_32,aint(hi(value)),tmplochi);
  429. cg.a_param_const(list,OS_32,aint(lo(value)),tmploclo);
  430. tmploclo.done;
  431. tmplochi.done;
  432. end;
  433. procedure tcg64f32.a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);
  434. var
  435. tmprefhi,tmpreflo : treference;
  436. tmploclo,tmplochi : tcgpara;
  437. begin
  438. tmploclo.init;
  439. tmplochi.init;
  440. splitparaloc64(paraloc,tmploclo,tmplochi);
  441. tmprefhi:=r;
  442. tmpreflo:=r;
  443. if target_info.endian=endian_big then
  444. inc(tmpreflo.offset,4)
  445. else
  446. inc(tmprefhi.offset,4);
  447. cg.a_param_ref(list,OS_32,tmprefhi,tmplochi);
  448. cg.a_param_ref(list,OS_32,tmpreflo,tmploclo);
  449. tmploclo.done;
  450. tmplochi.done;
  451. end;
  452. procedure tcg64f32.a_param64_loc(list : taasmoutput;const l:tlocation;const paraloc : tcgpara);
  453. begin
  454. case l.loc of
  455. LOC_REGISTER,
  456. LOC_CREGISTER :
  457. a_param64_reg(list,l.register64,paraloc);
  458. LOC_CONSTANT :
  459. a_param64_const(list,l.value64,paraloc);
  460. LOC_CREFERENCE,
  461. LOC_REFERENCE :
  462. a_param64_ref(list,l.reference,paraloc);
  463. else
  464. internalerror(200203287);
  465. end;
  466. end;
  467. procedure tcg64f32.g_rangecheck64(list : taasmoutput;const l:tlocation;fromdef,todef:tdef);
  468. var
  469. neglabel,
  470. poslabel,
  471. endlabel: tasmlabel;
  472. hreg : tregister;
  473. hdef : torddef;
  474. opsize : tcgsize;
  475. oldregisterdef: boolean;
  476. from_signed,to_signed: boolean;
  477. temploc : tlocation;
  478. begin
  479. from_signed := is_signed(fromdef);
  480. to_signed := is_signed(todef);
  481. if not is_64bit(todef) then
  482. begin
  483. oldregisterdef := registerdef;
  484. registerdef := false;
  485. { get the high dword in a register }
  486. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  487. begin
  488. hreg := l.register64.reghi;
  489. end
  490. else
  491. begin
  492. hreg:=cg.getintregister(list,OS_32);
  493. a_load64high_ref_reg(list,l.reference,hreg);
  494. end;
  495. objectlibrary.getlabel(poslabel);
  496. { check high dword, must be 0 (for positive numbers) }
  497. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  498. { It can also be $ffffffff, but only for negative numbers }
  499. if from_signed and to_signed then
  500. begin
  501. objectlibrary.getlabel(neglabel);
  502. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  503. end;
  504. { For all other values we have a range check error }
  505. cg.a_call_name(list,'FPC_RANGEERROR');
  506. { if the high dword = 0, the low dword can be considered a }
  507. { simple cardinal }
  508. cg.a_label(list,poslabel);
  509. hdef:=torddef.create(u32bit,0,$ffffffff);
  510. location_copy(temploc,l);
  511. temploc.size:=OS_32;
  512. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  513. (target_info.endian = endian_big) then
  514. inc(temploc.reference.offset,4);
  515. cg.g_rangecheck(list,temploc,hdef,todef);
  516. hdef.free;
  517. if from_signed and to_signed then
  518. begin
  519. objectlibrary.getlabel(endlabel);
  520. cg.a_jmp_always(list,endlabel);
  521. { if the high dword = $ffffffff, then the low dword (when }
  522. { considered as a longint) must be < 0 }
  523. cg.a_label(list,neglabel);
  524. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  525. begin
  526. hreg := l.register64.reglo;
  527. end
  528. else
  529. begin
  530. hreg:=cg.getintregister(list,OS_32);
  531. a_load64low_ref_reg(list,l.reference,hreg);
  532. end;
  533. { get a new neglabel (JM) }
  534. objectlibrary.getlabel(neglabel);
  535. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  536. cg.a_call_name(list,'FPC_RANGEERROR');
  537. { if we get here, the 64bit value lies between }
  538. { longint($80000000) and -1 (JM) }
  539. cg.a_label(list,neglabel);
  540. hdef:=torddef.create(s32bit,longint($80000000),-1);
  541. location_copy(temploc,l);
  542. temploc.size:=OS_32;
  543. cg.g_rangecheck(list,temploc,hdef,todef);
  544. hdef.free;
  545. cg.a_label(list,endlabel);
  546. end;
  547. registerdef := oldregisterdef;
  548. end
  549. else
  550. { todef = 64bit int }
  551. { no 64bit subranges supported, so only a small check is necessary }
  552. { if both are signed or both are unsigned, no problem! }
  553. if (from_signed xor to_signed) and
  554. { also not if the fromdef is unsigned and < 64bit, since that will }
  555. { always fit in a 64bit int (todef is 64bit) }
  556. (from_signed or
  557. (torddef(fromdef).typ = u64bit)) then
  558. begin
  559. { in all cases, there is only a problem if the higest bit is set }
  560. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  561. begin
  562. if is_64bit(fromdef) then
  563. begin
  564. hreg := l.register64.reghi;
  565. opsize := OS_32;
  566. end
  567. else
  568. begin
  569. hreg := l.register;
  570. opsize := def_cgsize(fromdef);
  571. end;
  572. end
  573. else
  574. begin
  575. hreg:=cg.getintregister(list,OS_32);
  576. opsize := def_cgsize(fromdef);
  577. if opsize in [OS_64,OS_S64] then
  578. a_load64high_ref_reg(list,l.reference,hreg)
  579. else
  580. cg.a_load_ref_reg(list,opsize,OS_32,l.reference,hreg);
  581. end;
  582. objectlibrary.getlabel(poslabel);
  583. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  584. cg.a_call_name(list,'FPC_RANGEERROR');
  585. cg.a_label(list,poslabel);
  586. end;
  587. end;
  588. function tcg64f32.optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : int64; var reg: tregister64): boolean;
  589. var
  590. lowvalue, highvalue : longint;
  591. hreg: tregister;
  592. begin
  593. lowvalue := longint(a);
  594. highvalue:= longint(a shr 32);
  595. { assume it will be optimized out }
  596. optimize64_op_const_reg := true;
  597. case op of
  598. OP_ADD:
  599. begin
  600. if a = 0 then
  601. exit;
  602. end;
  603. OP_AND:
  604. begin
  605. if lowvalue <> -1 then
  606. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  607. if highvalue <> -1 then
  608. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  609. { already emitted correctly }
  610. exit;
  611. end;
  612. OP_OR:
  613. begin
  614. if lowvalue <> 0 then
  615. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  616. if highvalue <> 0 then
  617. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  618. { already emitted correctly }
  619. exit;
  620. end;
  621. OP_SUB:
  622. begin
  623. if a = 0 then
  624. exit;
  625. end;
  626. OP_XOR:
  627. begin
  628. end;
  629. OP_SHL:
  630. begin
  631. if a = 0 then
  632. exit;
  633. { simply clear low-register
  634. and shift the rest and swap
  635. registers.
  636. }
  637. if (a > 31) then
  638. begin
  639. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  640. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  641. { swap the registers }
  642. hreg := reg.reghi;
  643. reg.reghi := reg.reglo;
  644. reg.reglo := hreg;
  645. exit;
  646. end;
  647. end;
  648. OP_SHR:
  649. begin
  650. if a = 0 then exit;
  651. { simply clear high-register
  652. and shift the rest and swap
  653. registers.
  654. }
  655. if (a > 31) then
  656. begin
  657. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  658. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  659. { swap the registers }
  660. hreg := reg.reghi;
  661. reg.reghi := reg.reglo;
  662. reg.reglo := hreg;
  663. exit;
  664. end;
  665. end;
  666. OP_IMUL,OP_MUL:
  667. begin
  668. if a = 1 then exit;
  669. end;
  670. OP_IDIV,OP_DIV:
  671. begin
  672. if a = 1 then exit;
  673. end;
  674. else
  675. internalerror(20020817);
  676. end;
  677. optimize64_op_const_reg := false;
  678. end;
  679. end.
  680. {
  681. $Log$
  682. Revision 1.66 2004-12-03 15:58:11 peter
  683. * LOC_CREGISTER fix
  684. Revision 1.65 2004/10/31 21:45:02 peter
  685. * generic tlocation
  686. * move tlocation to cgutils
  687. Revision 1.64 2004/10/15 09:14:16 mazen
  688. - remove $IFDEF DELPHI and related code
  689. - remove $IFDEF FPCPROCVAR and related code
  690. Revision 1.63 2004/09/25 14:23:54 peter
  691. * ungetregister is now only used for cpuregisters, renamed to
  692. ungetcpuregister
  693. * renamed (get|unget)explicitregister(s) to ..cpuregister
  694. * removed location-release/reference_release
  695. Revision 1.62 2004/09/21 17:25:12 peter
  696. * paraloc branch merged
  697. Revision 1.61.4.2 2004/09/20 20:46:34 peter
  698. * register allocation optimized for 64bit loading of parameters
  699. and return values
  700. Revision 1.61.4.1 2004/08/31 20:43:06 peter
  701. * paraloc patch
  702. Revision 1.61 2004/06/20 08:55:28 florian
  703. * logs truncated
  704. Revision 1.60 2004/06/18 15:16:46 peter
  705. * remove obsolete cardinal() typecasts
  706. Revision 1.59 2004/06/17 16:55:46 peter
  707. * powerpc compiles again
  708. Revision 1.58 2004/06/16 20:07:07 florian
  709. * dwarf branch merged
  710. Revision 1.57.2.5 2004/06/13 10:51:16 florian
  711. * fixed several register allocator problems (sparc/arm)
  712. Revision 1.57.2.4 2004/06/12 17:01:01 florian
  713. * fixed compilation of arm compiler
  714. }