cg64f32.pas 28 KB

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