cg64f32.pas 28 KB

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