cg64f32.pas 28 KB

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