cg64f32.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  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,aasmdata,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 : TAsmList;value : int64;const ref : treference);override;
  37. procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
  38. procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
  39. procedure a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);override;
  40. procedure a_load64_const_reg(list : TAsmList;value: int64;reg : tregister64);override;
  41. procedure a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);override;
  42. procedure a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);override;
  43. procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);override;
  44. procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
  45. procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
  46. procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
  47. procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
  48. procedure a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
  49. procedure a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
  50. procedure a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
  51. procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
  52. procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
  53. procedure a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);override;
  54. procedure a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);override;
  55. procedure a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);override;
  56. procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
  57. procedure a_param64_reg(list : TAsmList;reg : tregister64;const paraloc : tcgpara);override;
  58. procedure a_param64_const(list : TAsmList;value : int64;const paraloc : tcgpara);override;
  59. procedure a_param64_ref(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
  60. procedure a_param64_loc(list : TAsmList;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: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
  67. procedure g_rangecheck64(list: TAsmList; 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,symtable,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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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,aint(hi(l.value64)),reg);
  347. else
  348. internalerror(200203244);
  349. end;
  350. end;
  351. procedure tcg64f32.a_op64_const_loc(list : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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 : TAsmList;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. from_signed,to_signed: boolean;
  488. temploc : tlocation;
  489. begin
  490. from_signed := is_signed(fromdef);
  491. to_signed := is_signed(todef);
  492. if not is_64bit(todef) then
  493. begin
  494. { get the high dword in a register }
  495. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  496. begin
  497. hreg := l.register64.reghi;
  498. end
  499. else
  500. begin
  501. hreg:=cg.getintregister(list,OS_32);
  502. a_load64high_ref_reg(list,l.reference,hreg);
  503. end;
  504. current_asmdata.getjumplabel(poslabel);
  505. { check high dword, must be 0 (for positive numbers) }
  506. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  507. { It can also be $ffffffff, but only for negative numbers }
  508. if from_signed and to_signed then
  509. begin
  510. current_asmdata.getjumplabel(neglabel);
  511. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
  512. end;
  513. { For all other values we have a range check error }
  514. cg.a_call_name(list,'FPC_RANGEERROR');
  515. { if the high dword = 0, the low dword can be considered a }
  516. { simple cardinal }
  517. cg.a_label(list,poslabel);
  518. hdef:=torddef.create(u32bit,0,$ffffffff);
  519. location_copy(temploc,l);
  520. temploc.size:=OS_32;
  521. if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  522. (target_info.endian = endian_big) then
  523. inc(temploc.reference.offset,4);
  524. cg.g_rangecheck(list,temploc,hdef,todef);
  525. hdef.free;
  526. if from_signed and to_signed then
  527. begin
  528. current_asmdata.getjumplabel(endlabel);
  529. cg.a_jmp_always(list,endlabel);
  530. { if the high dword = $ffffffff, then the low dword (when }
  531. { considered as a longint) must be < 0 }
  532. cg.a_label(list,neglabel);
  533. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  534. begin
  535. hreg := l.register64.reglo;
  536. end
  537. else
  538. begin
  539. hreg:=cg.getintregister(list,OS_32);
  540. a_load64low_ref_reg(list,l.reference,hreg);
  541. end;
  542. { get a new neglabel (JM) }
  543. current_asmdata.getjumplabel(neglabel);
  544. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  545. cg.a_call_name(list,'FPC_RANGEERROR');
  546. { if we get here, the 64bit value lies between }
  547. { longint($80000000) and -1 (JM) }
  548. cg.a_label(list,neglabel);
  549. hdef:=torddef.create(s32bit,longint($80000000),-1);
  550. location_copy(temploc,l);
  551. temploc.size:=OS_32;
  552. cg.g_rangecheck(list,temploc,hdef,todef);
  553. hdef.free;
  554. cg.a_label(list,endlabel);
  555. end;
  556. end
  557. else
  558. { todef = 64bit int }
  559. { no 64bit subranges supported, so only a small check is necessary }
  560. { if both are signed or both are unsigned, no problem! }
  561. if (from_signed xor to_signed) and
  562. { also not if the fromdef is unsigned and < 64bit, since that will }
  563. { always fit in a 64bit int (todef is 64bit) }
  564. (from_signed or
  565. (torddef(fromdef).typ = u64bit)) then
  566. begin
  567. { in all cases, there is only a problem if the higest bit is set }
  568. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  569. begin
  570. if is_64bit(fromdef) then
  571. begin
  572. hreg := l.register64.reghi;
  573. opsize := OS_32;
  574. end
  575. else
  576. begin
  577. hreg := l.register;
  578. opsize := def_cgsize(fromdef);
  579. end;
  580. end
  581. else
  582. begin
  583. hreg:=cg.getintregister(list,OS_32);
  584. opsize:=OS_32;
  585. if l.size in [OS_64,OS_S64] then
  586. a_load64high_ref_reg(list,l.reference,hreg)
  587. else
  588. cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
  589. end;
  590. current_asmdata.getjumplabel(poslabel);
  591. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  592. cg.a_call_name(list,'FPC_RANGEERROR');
  593. cg.a_label(list,poslabel);
  594. end;
  595. end;
  596. function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
  597. var
  598. lowvalue, highvalue : longint;
  599. hreg: tregister;
  600. begin
  601. lowvalue := longint(a);
  602. highvalue:= longint(a shr 32);
  603. { assume it will be optimized out }
  604. optimize64_op_const_reg := true;
  605. case op of
  606. OP_ADD:
  607. begin
  608. if a = 0 then
  609. exit;
  610. end;
  611. OP_AND:
  612. begin
  613. if lowvalue <> -1 then
  614. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  615. if highvalue <> -1 then
  616. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  617. { already emitted correctly }
  618. exit;
  619. end;
  620. OP_OR:
  621. begin
  622. if lowvalue <> 0 then
  623. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  624. if highvalue <> 0 then
  625. cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
  626. { already emitted correctly }
  627. exit;
  628. end;
  629. OP_SUB:
  630. begin
  631. if a = 0 then
  632. exit;
  633. end;
  634. OP_XOR:
  635. begin
  636. end;
  637. OP_SHL:
  638. begin
  639. if a = 0 then
  640. exit;
  641. { simply clear low-register
  642. and shift the rest and swap
  643. registers.
  644. }
  645. if (a > 31) then
  646. begin
  647. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  648. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
  649. { swap the registers }
  650. hreg := reg.reghi;
  651. reg.reghi := reg.reglo;
  652. reg.reglo := hreg;
  653. exit;
  654. end;
  655. end;
  656. OP_SHR:
  657. begin
  658. if a = 0 then exit;
  659. { simply clear high-register
  660. and shift the rest and swap
  661. registers.
  662. }
  663. if (a > 31) then
  664. begin
  665. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  666. cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
  667. { swap the registers }
  668. hreg := reg.reghi;
  669. reg.reghi := reg.reglo;
  670. reg.reglo := hreg;
  671. exit;
  672. end;
  673. end;
  674. OP_IMUL,OP_MUL:
  675. begin
  676. if a = 1 then exit;
  677. end;
  678. OP_IDIV,OP_DIV:
  679. begin
  680. if a = 1 then exit;
  681. end;
  682. else
  683. internalerror(20020817);
  684. end;
  685. optimize64_op_const_reg := false;
  686. end;
  687. end.