cg64f32.pas 29 KB

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