cg64f32.pas 32 KB

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