cg64f32.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Member of the Free Pascal development team
  5. This unit implements the code generation for 64 bit int
  6. arithmethics on 32 bit processors
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. {# This unit implements the code generation for 64 bit int arithmethics on
  21. 32 bit processors.
  22. }
  23. unit cg64f32;
  24. {$i fpcdefs.inc}
  25. interface
  26. uses
  27. aasmbase,aasmtai,aasmcpu,
  28. cpuinfo, cpubase,
  29. cginfo, cgobj,
  30. node,symtype;
  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_reg_alloc(list : taasmoutput;r : tregister64);override;
  37. procedure a_reg_dealloc(list : taasmoutput;r : tregister64);override;
  38. procedure a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);override;
  39. procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);override;
  40. procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);override;
  41. procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);override;
  42. procedure a_load64_const_reg(list : taasmoutput;value: qword;reg : tregister64);override;
  43. procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);override;
  44. procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);override;
  45. procedure a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);override;
  46. procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);override;
  47. procedure a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);override;
  48. procedure a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);override;
  49. procedure a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);override;
  50. procedure a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);override;
  51. procedure a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);override;
  52. procedure a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);override;
  53. procedure a_op64_const_loc(list : taasmoutput;op:TOpCG;value : qword;const l: tlocation);override;
  54. procedure a_op64_reg_loc(list : taasmoutput;op:TOpCG;reg : tregister64;const l : tlocation);override;
  55. procedure a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reg : tregister64);override;
  56. procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);override;
  57. procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;value : qword;const ref : treference);override;
  58. procedure a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);override;
  59. procedure a_param64_const(list : taasmoutput;value : qword;const locpara : tparalocation);override;
  60. procedure a_param64_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);override;
  61. procedure a_param64_loc(list : taasmoutput;const l : tlocation;const locpara : tparalocation);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 : qword; var reg: tregister64): boolean;override;
  68. procedure g_rangecheck64(list: taasmoutput; const p: tnode;
  69. const todef: tdef); override;
  70. end;
  71. {# Creates a tregister64 record from 2 32 Bit registers. }
  72. function joinreg64(reglo,reghi : tregister) : tregister64;
  73. implementation
  74. uses
  75. globtype,globals,systems,
  76. cgbase,
  77. verbose,
  78. symbase,symconst,symdef,defbase;
  79. function joinreg64(reglo,reghi : tregister) : tregister64;
  80. begin
  81. result.reglo:=reglo;
  82. result.reghi:=reghi;
  83. end;
  84. procedure tcg64f32.a_reg_alloc(list : taasmoutput;r : tregister64);
  85. begin
  86. list.concat(tai_regalloc.alloc(r.reglo));
  87. list.concat(tai_regalloc.alloc(r.reghi));
  88. end;
  89. procedure tcg64f32.a_reg_dealloc(list : taasmoutput;r : tregister64);
  90. begin
  91. list.concat(tai_regalloc.dealloc(r.reglo));
  92. list.concat(tai_regalloc.dealloc(r.reghi));
  93. end;
  94. procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);
  95. var
  96. tmpreg: tregister;
  97. tmpref: treference;
  98. begin
  99. if target_info.endian = endian_big then
  100. begin
  101. tmpreg:=reg.reglo;
  102. reg.reglo:=reg.reghi;
  103. reg.reghi:=tmpreg;
  104. end;
  105. cg.a_load_reg_ref(list,OS_32,reg.reglo,ref);
  106. tmpref := ref;
  107. inc(tmpref.offset,4);
  108. cg.a_load_reg_ref(list,OS_32,reg.reghi,tmpref);
  109. end;
  110. procedure tcg64f32.a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);
  111. var
  112. tmpvalue : DWord;
  113. tmpref: treference;
  114. begin
  115. if target_info.endian = endian_big then
  116. swap_qword(value);
  117. cg.a_load_const_ref(list,OS_32,lo(value),ref);
  118. tmpref := ref;
  119. inc(tmpref.offset,4);
  120. cg.a_load_const_ref(list,OS_32,hi(value),tmpref);
  121. end;
  122. procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);
  123. var
  124. tmpreg: tregister;
  125. tmpref: treference;
  126. got_scratch: boolean;
  127. begin
  128. if target_info.endian = endian_big then
  129. begin
  130. tmpreg := reg.reglo;
  131. reg.reglo := reg.reghi;
  132. reg.reghi := tmpreg;
  133. end;
  134. got_scratch:=false;
  135. tmpref := ref;
  136. if (tmpref.base=reg.reglo) then
  137. begin
  138. tmpreg := cg.get_scratch_reg_int(list);
  139. got_scratch:=true;
  140. cg.a_load_reg_reg(list,OS_ADDR,tmpref.base,tmpreg);
  141. tmpref.base:=tmpreg;
  142. end
  143. else
  144. { this works only for the i386, thus the i386 needs to override }
  145. { this method and this method must be replaced by a more generic }
  146. { implementation FK }
  147. if (tmpref.index=reg.reglo) then
  148. begin
  149. tmpreg:=cg.get_scratch_reg_int(list);
  150. got_scratch:=true;
  151. cg.a_load_reg_reg(list,OS_ADDR,tmpref.index,tmpreg);
  152. tmpref.index:=tmpreg;
  153. end;
  154. cg.a_load_ref_reg(list,OS_32,tmpref,reg.reglo);
  155. inc(tmpref.offset,4);
  156. cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
  157. if got_scratch then
  158. cg.free_scratch_reg(list,tmpreg);
  159. end;
  160. procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);
  161. begin
  162. cg.a_load_reg_reg(list,OS_32,regsrc.reglo,regdst.reglo);
  163. cg.a_load_reg_reg(list,OS_32,regsrc.reghi,regdst.reghi);
  164. end;
  165. procedure tcg64f32.a_load64_const_reg(list : taasmoutput;value : qword;reg : tregister64);
  166. begin
  167. cg.a_load_const_reg(list,OS_32,lo(value),reg.reglo);
  168. cg.a_load_const_reg(list,OS_32,hi(value),reg.reghi);
  169. end;
  170. procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);
  171. begin
  172. case l.loc of
  173. LOC_REFERENCE, LOC_CREFERENCE:
  174. a_load64_ref_reg(list,l.reference,reg);
  175. LOC_REGISTER,LOC_CREGISTER:
  176. a_load64_reg_reg(list,l.register64,reg);
  177. LOC_CONSTANT :
  178. a_load64_const_reg(list,l.valueqword,reg);
  179. else
  180. internalerror(200112292);
  181. end;
  182. end;
  183. procedure tcg64f32.a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);
  184. begin
  185. case l.loc of
  186. LOC_REGISTER,LOC_CREGISTER:
  187. a_load64_reg_ref(list,l.reg64,ref);
  188. LOC_CONSTANT :
  189. a_load64_const_ref(list,l.valueqword,ref);
  190. else
  191. internalerror(200203288);
  192. end;
  193. end;
  194. procedure tcg64f32.a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);
  195. begin
  196. case l.loc of
  197. LOC_REFERENCE, LOC_CREFERENCE:
  198. a_load64_const_ref(list,value,l.reference);
  199. LOC_REGISTER,LOC_CREGISTER:
  200. a_load64_const_reg(list,value,l.reg64);
  201. else
  202. internalerror(200112293);
  203. end;
  204. end;
  205. procedure tcg64f32.a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);
  206. begin
  207. case l.loc of
  208. LOC_REFERENCE, LOC_CREFERENCE:
  209. a_load64_reg_ref(list,reg,l.reference);
  210. LOC_REGISTER,LOC_CREGISTER:
  211. a_load64_reg_reg(list,reg,l.register64);
  212. else
  213. internalerror(200112293);
  214. end;
  215. end;
  216. procedure tcg64f32.a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
  217. var
  218. tmpref: treference;
  219. begin
  220. if target_info.endian = endian_big then
  221. cg.a_load_reg_ref(list,OS_32,reg,ref)
  222. else
  223. begin
  224. tmpref := ref;
  225. inc(tmpref.offset,4);
  226. cg.a_load_reg_ref(list,OS_32,reg,tmpref)
  227. end;
  228. end;
  229. procedure tcg64f32.a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
  230. var
  231. tmpref: treference;
  232. begin
  233. if target_info.endian = endian_little then
  234. cg.a_load_reg_ref(list,OS_32,reg,ref)
  235. else
  236. begin
  237. tmpref := ref;
  238. inc(tmpref.offset,4);
  239. cg.a_load_reg_ref(list,OS_32,reg,tmpref)
  240. end;
  241. end;
  242. procedure tcg64f32.a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
  243. var
  244. tmpref: treference;
  245. begin
  246. if target_info.endian = endian_big then
  247. cg.a_load_ref_reg(list,OS_32,ref,reg)
  248. else
  249. begin
  250. tmpref := ref;
  251. inc(tmpref.offset,4);
  252. cg.a_load_ref_reg(list,OS_32,tmpref,reg)
  253. end;
  254. end;
  255. procedure tcg64f32.a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
  256. var
  257. tmpref: treference;
  258. begin
  259. if target_info.endian = endian_little then
  260. cg.a_load_ref_reg(list,OS_32,ref,reg)
  261. else
  262. begin
  263. tmpref := ref;
  264. inc(tmpref.offset,4);
  265. cg.a_load_ref_reg(list,OS_32,tmpref,reg)
  266. end;
  267. end;
  268. procedure tcg64f32.a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  269. begin
  270. case l.loc of
  271. LOC_REFERENCE,
  272. LOC_CREFERENCE :
  273. a_load64low_ref_reg(list,l.reference,reg);
  274. LOC_REGISTER :
  275. cg.a_load_reg_reg(list,OS_32,l.registerlow,reg);
  276. LOC_CONSTANT :
  277. cg.a_load_const_reg(list,OS_32,lo(l.valueqword),reg);
  278. else
  279. internalerror(200203244);
  280. end;
  281. end;
  282. procedure tcg64f32.a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  283. begin
  284. case l.loc of
  285. LOC_REFERENCE,
  286. LOC_CREFERENCE :
  287. a_load64high_ref_reg(list,l.reference,reg);
  288. LOC_REGISTER :
  289. cg.a_load_reg_reg(list,OS_32,l.registerhigh,reg);
  290. LOC_CONSTANT :
  291. cg.a_load_const_reg(list,OS_32,hi(l.valueqword),reg);
  292. else
  293. internalerror(200203244);
  294. end;
  295. end;
  296. procedure tcg64f32.a_op64_const_loc(list : taasmoutput;op:TOpCG;value : qword;const l: tlocation);
  297. begin
  298. case l.loc of
  299. LOC_REFERENCE, LOC_CREFERENCE:
  300. a_op64_const_ref(list,op,value,l.reference);
  301. LOC_REGISTER,LOC_CREGISTER:
  302. a_op64_const_reg(list,op,value,l.register64);
  303. else
  304. internalerror(200203292);
  305. end;
  306. end;
  307. procedure tcg64f32.a_op64_reg_loc(list : taasmoutput;op:TOpCG;reg : tregister64;const l : tlocation);
  308. begin
  309. case l.loc of
  310. LOC_REFERENCE, LOC_CREFERENCE:
  311. a_op64_reg_ref(list,op,reg,l.reference);
  312. LOC_REGISTER,LOC_CREGISTER:
  313. a_op64_reg_reg(list,op,reg,l.register64);
  314. else
  315. internalerror(2002032422);
  316. end;
  317. end;
  318. procedure tcg64f32.a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reg : tregister64);
  319. begin
  320. case l.loc of
  321. LOC_REFERENCE, LOC_CREFERENCE:
  322. a_op64_ref_reg(list,op,l.reference,reg);
  323. LOC_REGISTER,LOC_CREGISTER:
  324. a_op64_reg_reg(list,op,l.register64,reg);
  325. LOC_CONSTANT :
  326. a_op64_const_reg(list,op,l.valueqword,reg);
  327. else
  328. internalerror(200203242);
  329. end;
  330. end;
  331. procedure tcg64f32.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);
  332. var
  333. tempreg: tregister64;
  334. begin
  335. tempreg.reghi := cg.get_scratch_reg_int(list);
  336. tempreg.reglo := cg.get_scratch_reg_int(list);
  337. a_load64_ref_reg(list,ref,tempreg);
  338. a_op64_reg_reg(list,op,tempreg,reg);
  339. cg.free_scratch_reg(list,tempreg.reglo);
  340. cg.free_scratch_reg(list,tempreg.reghi);
  341. end;
  342. procedure tcg64f32.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : qword;const ref : treference);
  343. var
  344. tempreg: tregister64;
  345. begin
  346. tempreg.reghi := cg.get_scratch_reg_int(list);
  347. tempreg.reglo := cg.get_scratch_reg_int(list);
  348. a_load64_ref_reg(list,ref,tempreg);
  349. a_op64_const_reg(list,op,value,tempreg);
  350. a_load64_reg_ref(list,tempreg,ref);
  351. cg.free_scratch_reg(list,tempreg.reglo);
  352. cg.free_scratch_reg(list,tempreg.reghi);
  353. end;
  354. procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);
  355. begin
  356. {$warning FIX ME}
  357. cg.a_param_reg(list,OS_32,reg.reghi,locpara);
  358. { the nr+1 needs definitivly a fix FK }
  359. { maybe the parameter numbering needs }
  360. { to take care of this on 32 Bit }
  361. { systems FK }
  362. cg.a_param_reg(list,OS_32,reg.reglo,locpara);
  363. end;
  364. procedure tcg64f32.a_param64_const(list : taasmoutput;value : qword;const locpara : tparalocation);
  365. begin
  366. {$warning FIX ME}
  367. if target_info.endian = endian_big then
  368. swap_qword(value);
  369. cg.a_param_const(list,OS_32,hi(value),locpara);
  370. { the nr+1 needs definitivly a fix FK }
  371. { maybe the parameter numbering needs }
  372. { to take care of this on 32 Bit }
  373. { systems FK }
  374. cg.a_param_const(list,OS_32,lo(value),locpara);
  375. end;
  376. procedure tcg64f32.a_param64_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  377. var
  378. tmpref: treference;
  379. begin
  380. {$warning FIX ME}
  381. tmpref := r;
  382. inc(tmpref.offset,4);
  383. cg.a_param_ref(list,OS_32,tmpref,locpara);
  384. { the nr+1 needs definitivly a fix FK }
  385. { maybe the parameter numbering needs }
  386. { to take care of this on 32 Bit }
  387. { systems FK }
  388. cg.a_param_ref(list,OS_32,r,locpara);
  389. end;
  390. procedure tcg64f32.a_param64_loc(list : taasmoutput;const l:tlocation;const locpara : tparalocation);
  391. begin
  392. {$warning FIX ME}
  393. case l.loc of
  394. LOC_REGISTER,
  395. LOC_CREGISTER :
  396. a_param64_reg(list,l.register64,locpara);
  397. LOC_CONSTANT :
  398. a_param64_const(list,l.valueqword,locpara);
  399. LOC_CREFERENCE,
  400. LOC_REFERENCE :
  401. a_param64_ref(list,l.reference,locpara);
  402. else
  403. internalerror(200203287);
  404. end;
  405. end;
  406. procedure tcg64f32.g_rangecheck64(list : taasmoutput;const p : tnode;const todef : tdef);
  407. var
  408. neglabel,
  409. poslabel,
  410. endlabel: tasmlabel;
  411. hreg : tregister;
  412. hdef : torddef;
  413. fromdef : tdef;
  414. opsize : tcgsize;
  415. oldregisterdef: boolean;
  416. from_signed,to_signed: boolean;
  417. got_scratch: boolean;
  418. begin
  419. fromdef:=p.resulttype.def;
  420. from_signed := is_signed(fromdef);
  421. to_signed := is_signed(todef);
  422. if not is_64bitint(todef) then
  423. begin
  424. oldregisterdef := registerdef;
  425. registerdef := false;
  426. { get the high dword in a register }
  427. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  428. begin
  429. hreg := p.location.registerhigh;
  430. got_scratch := false
  431. end
  432. else
  433. begin
  434. hreg := cg.get_scratch_reg_int(list);
  435. got_scratch := true;
  436. a_load64high_ref_reg(list,p.location.reference,hreg);
  437. end;
  438. objectlibrary.getlabel(poslabel);
  439. { check high dword, must be 0 (for positive numbers) }
  440. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  441. { It can also be $ffffffff, but only for negative numbers }
  442. if from_signed and to_signed then
  443. begin
  444. objectlibrary.getlabel(neglabel);
  445. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,aword(-1),hreg,neglabel);
  446. end;
  447. { !!! freeing of register should happen directly after compare! (JM) }
  448. if got_scratch then
  449. cg.free_scratch_reg(list,hreg);
  450. { For all other values we have a range check error }
  451. cg.a_call_name(list,'FPC_RANGEERROR');
  452. { if the high dword = 0, the low dword can be considered a }
  453. { simple cardinal }
  454. cg.a_label(list,poslabel);
  455. hdef:=torddef.create(u32bit,0,cardinal($ffffffff));
  456. { the real p.resulttype.def is already saved in fromdef }
  457. p.resulttype.def := hdef;
  458. { no use in calling just "g_rangecheck" since that one will }
  459. { simply call the inherited method too (JM) }
  460. cg.g_rangecheck(list,p,todef);
  461. hdef.free;
  462. { restore original resulttype.def }
  463. p.resulttype.def := todef;
  464. if from_signed and to_signed then
  465. begin
  466. objectlibrary.getlabel(endlabel);
  467. cg.a_jmp_always(list,endlabel);
  468. { if the high dword = $ffffffff, then the low dword (when }
  469. { considered as a longint) must be < 0 }
  470. cg.a_label(list,neglabel);
  471. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  472. begin
  473. hreg := p.location.registerlow;
  474. got_scratch := false
  475. end
  476. else
  477. begin
  478. hreg := cg.get_scratch_reg_int(list);
  479. got_scratch := true;
  480. a_load64low_ref_reg(list,p.location.reference,hreg);
  481. end;
  482. { get a new neglabel (JM) }
  483. objectlibrary.getlabel(neglabel);
  484. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  485. { !!! freeing of register should happen directly after compare! (JM) }
  486. if got_scratch then
  487. cg.free_scratch_reg(list,hreg);
  488. cg.a_call_name(list,'FPC_RANGEERROR');
  489. { if we get here, the 64bit value lies between }
  490. { longint($80000000) and -1 (JM) }
  491. cg.a_label(list,neglabel);
  492. hdef:=torddef.create(s32bit,longint($80000000),-1);
  493. p.resulttype.def := hdef;
  494. cg.g_rangecheck(list,p,todef);
  495. hdef.free;
  496. cg.a_label(list,endlabel);
  497. end;
  498. registerdef := oldregisterdef;
  499. p.resulttype.def := fromdef;
  500. { restore p's resulttype.def }
  501. end
  502. else
  503. { todef = 64bit int }
  504. { no 64bit subranges supported, so only a small check is necessary }
  505. { if both are signed or both are unsigned, no problem! }
  506. if (from_signed xor to_signed) and
  507. { also not if the fromdef is unsigned and < 64bit, since that will }
  508. { always fit in a 64bit int (todef is 64bit) }
  509. (from_signed or
  510. (torddef(fromdef).typ = u64bit)) then
  511. begin
  512. { in all cases, there is only a problem if the higest bit is set }
  513. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  514. begin
  515. if is_64bitint(fromdef) then
  516. begin
  517. hreg := p.location.registerhigh;
  518. opsize := OS_32;
  519. end
  520. else
  521. begin
  522. hreg := p.location.register;
  523. opsize := def_cgsize(p.resulttype.def);
  524. end;
  525. got_scratch := false;
  526. end
  527. else
  528. begin
  529. hreg := cg.get_scratch_reg_int(list);
  530. got_scratch := true;
  531. opsize := def_cgsize(p.resulttype.def);
  532. if opsize in [OS_64,OS_S64] then
  533. a_load64high_ref_reg(list,p.location.reference,hreg)
  534. else
  535. cg.a_load_ref_reg(list,opsize,p.location.reference,hreg);
  536. end;
  537. objectlibrary.getlabel(poslabel);
  538. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  539. { !!! freeing of register should happen directly after compare! (JM) }
  540. if got_scratch then
  541. cg.free_scratch_reg(list,hreg);
  542. cg.a_call_name(list,'FPC_RANGEERROR');
  543. cg.a_label(list,poslabel);
  544. end;
  545. end;
  546. function tcg64f32.optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : qword; var reg: tregister64): boolean;
  547. var
  548. lowvalue, highvalue : cardinal;
  549. hreg: tregister;
  550. begin
  551. lowvalue := cardinal(a);
  552. highvalue:= a shr 32;
  553. { assume it will be optimized out }
  554. optimize64_op_const_reg := true;
  555. case op of
  556. OP_ADD:
  557. begin
  558. if a = 0 then
  559. exit;
  560. end;
  561. OP_AND:
  562. begin
  563. if lowvalue <> high(cardinal) then
  564. cg.a_op_const_reg(list,op,lowvalue,reg.reglo);
  565. if highvalue <> high(cardinal) then
  566. cg.a_op_const_reg(list,op,highvalue,reg.reghi);
  567. { already emitted correctly }
  568. exit;
  569. end;
  570. OP_OR:
  571. begin
  572. if lowvalue <> 0 then
  573. cg.a_op_const_reg(list,op,lowvalue,reg.reglo);
  574. if highvalue <> 0 then
  575. cg.a_op_const_reg(list,op,highvalue,reg.reghi);
  576. { already emitted correctly }
  577. exit;
  578. end;
  579. OP_SUB:
  580. begin
  581. if a = 0 then
  582. exit;
  583. end;
  584. OP_XOR:
  585. begin
  586. end;
  587. OP_SHL:
  588. begin
  589. if a = 0 then
  590. exit;
  591. { simply clear low-register
  592. and shift the rest and swap
  593. registers.
  594. }
  595. if (a > 31) then
  596. begin
  597. cg.a_load_const_reg(list,OS_32,0,reg.reglo);
  598. cg.a_op_const_reg(list,OP_SHL,a mod 32,reg.reghi);
  599. { swap the registers }
  600. hreg := reg.reghi;
  601. reg.reghi := reg.reglo;
  602. reg.reglo := hreg;
  603. exit;
  604. end;
  605. end;
  606. OP_SHR:
  607. begin
  608. if a = 0 then exit;
  609. { simply clear high-register
  610. and shift the rest and swap
  611. registers.
  612. }
  613. if (a > 31) then
  614. begin
  615. cg.a_load_const_reg(list,OS_32,0,reg.reghi);
  616. cg.a_op_const_reg(list,OP_SHL,a mod 32,reg.reglo);
  617. { swap the registers }
  618. hreg := reg.reghi;
  619. reg.reghi := reg.reglo;
  620. reg.reglo := hreg;
  621. exit;
  622. end;
  623. end;
  624. OP_IMUL,OP_MUL:
  625. begin
  626. if a = 1 then exit;
  627. end;
  628. OP_IDIV,OP_DIV:
  629. begin
  630. if a = 1 then exit;
  631. end;
  632. else
  633. internalerror(20020817);
  634. end;
  635. optimize64_op_const_reg := false;
  636. end;
  637. (*
  638. procedure int64f32_assignment_int64_reg(p : passignmentnode);
  639. begin
  640. end;
  641. begin
  642. p2_assignment:=@int64f32_assignement_int64;
  643. *)
  644. end.
  645. {
  646. $Log$
  647. Revision 1.27 2002-08-19 18:17:47 carl
  648. + optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
  649. * more fixes to m68k for 64-bit operations
  650. Revision 1.26 2002/08/17 22:09:43 florian
  651. * result type handling in tcgcal.pass_2 overhauled
  652. * better tnode.dowrite
  653. * some ppc stuff fixed
  654. Revision 1.25 2002/08/14 18:41:47 jonas
  655. - remove valuelow/valuehigh fields from tlocation, because they depend
  656. on the endianess of the host operating system -> difficult to get
  657. right. Use lo/hi(location.valueqword) instead (remember to use
  658. valueqword and not value!!)
  659. Revision 1.24 2002/08/11 14:32:26 peter
  660. * renamed current_library to objectlibrary
  661. Revision 1.23 2002/08/11 13:24:11 peter
  662. * saving of asmsymbols in ppu supported
  663. * asmsymbollist global is removed and moved into a new class
  664. tasmlibrarydata that will hold the info of a .a file which
  665. corresponds with a single module. Added librarydata to tmodule
  666. to keep the library info stored for the module. In the future the
  667. objectfiles will also be stored to the tasmlibrarydata class
  668. * all getlabel/newasmsymbol and friends are moved to the new class
  669. Revision 1.22 2002/07/28 15:57:15 jonas
  670. * fixed a_load64_const_reg() for big endian systems
  671. Revision 1.21 2002/07/20 11:57:52 florian
  672. * types.pas renamed to defbase.pas because D6 contains a types
  673. unit so this would conflicts if D6 programms are compiled
  674. + Willamette/SSE2 instructions to assembler added
  675. Revision 1.20 2002/07/12 10:14:26 jonas
  676. * some big-endian fixes
  677. Revision 1.19 2002/07/11 07:23:17 jonas
  678. + generic implementations of a_op64_ref_reg() and a_op64_const_ref()
  679. (only works for processors with >2 scratch registers)
  680. Revision 1.18 2002/07/10 11:12:44 jonas
  681. * fixed a_op64_const_loc()
  682. Revision 1.17 2002/07/07 09:52:32 florian
  683. * powerpc target fixed, very simple units can be compiled
  684. * some basic stuff for better callparanode handling, far from being finished
  685. Revision 1.16 2002/07/01 18:46:21 peter
  686. * internal linker
  687. * reorganized aasm layer
  688. Revision 1.15 2002/07/01 16:23:52 peter
  689. * cg64 patch
  690. * basics for currency
  691. * asnode updates for class and interface (not finished)
  692. Revision 1.14 2002/05/20 13:30:40 carl
  693. * bugfix of hdisponen (base must be set, not index)
  694. * more portability fixes
  695. Revision 1.13 2002/05/18 13:34:05 peter
  696. * readded missing revisions
  697. Revision 1.12 2002/05/16 19:46:35 carl
  698. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  699. + try to fix temp allocation (still in ifdef)
  700. + generic constructor calls
  701. + start of tassembler / tmodulebase class cleanup
  702. Revision 1.10 2002/05/12 16:53:04 peter
  703. * moved entry and exitcode to ncgutil and cgobj
  704. * foreach gets extra argument for passing local data to the
  705. iterator function
  706. * -CR checks also class typecasts at runtime by changing them
  707. into as
  708. * fixed compiler to cycle with the -CR option
  709. * fixed stabs with elf writer, finally the global variables can
  710. be watched
  711. * removed a lot of routines from cga unit and replaced them by
  712. calls to cgobj
  713. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  714. u32bit then the other is typecasted also to u32bit without giving
  715. a rangecheck warning/error.
  716. * fixed pascal calling method with reversing also the high tree in
  717. the parast, detected by tcalcst3 test
  718. Revision 1.9 2002/04/25 20:16:38 peter
  719. * moved more routines from cga/n386util
  720. Revision 1.8 2002/04/21 15:28:51 carl
  721. * a_jmp_cond -> a_jmp_always
  722. Revision 1.7 2002/04/07 13:21:18 carl
  723. + more documentation
  724. Revision 1.6 2002/04/03 10:41:35 jonas
  725. + a_load64_const_loc method
  726. Revision 1.5 2002/04/02 17:11:27 peter
  727. * tlocation,treference update
  728. * LOC_CONSTANT added for better constant handling
  729. * secondadd splitted in multiple routines
  730. * location_force_reg added for loading a location to a register
  731. of a specified size
  732. * secondassignment parses now first the right and then the left node
  733. (this is compatible with Kylix). This saves a lot of push/pop especially
  734. with string operations
  735. * adapted some routines to use the new cg methods
  736. Revision 1.4 2002/03/04 19:10:11 peter
  737. * removed compiler warnings
  738. Revision 1.3 2002/01/24 12:33:52 jonas
  739. * adapted ranges of native types to int64 (e.g. high cardinal is no
  740. longer longint($ffffffff), but just $fffffff in psystem)
  741. * small additional fix in 64bit rangecheck code generation for 32 bit
  742. processors
  743. * adaption of ranges required the matching talgorithm used for selecting
  744. which overloaded procedure to call to be adapted. It should now always
  745. select the closest match for ordinal parameters.
  746. + inttostr(qword) in sysstr.inc/sysstrh.inc
  747. + abs(int64), sqr(int64), sqr(qword) in systemh.inc/generic.inc (previous
  748. fixes were required to be able to add them)
  749. * is_in_limit() moved from ncal to types unit, should always be used
  750. instead of direct comparisons of low/high values of orddefs because
  751. qword is a special case
  752. }