cg64f32.pas 32 KB

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