cg64f32.pas 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  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{$ifdef newra};delete:boolean{$endif});override;
  45. procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64{$ifdef newra};delete:boolean{$endif});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{$ifdef newra};delete: boolean{$endif});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 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,globals,systems,
  80. cgbase,
  81. verbose,
  82. symbase,symconst,symdef,defutil,rgobj,tgobj;
  83. function joinreg64(reglo,reghi : tregister) : tregister64;
  84. begin
  85. result.reglo:=reglo;
  86. result.reghi:=reghi;
  87. end;
  88. procedure tcg64f32.a_reg_alloc(list : taasmoutput;r : tregister64);
  89. begin
  90. list.concat(tai_regalloc.alloc(r.reglo));
  91. list.concat(tai_regalloc.alloc(r.reghi));
  92. end;
  93. procedure tcg64f32.a_reg_dealloc(list : taasmoutput;r : tregister64);
  94. begin
  95. list.concat(tai_regalloc.dealloc(r.reglo));
  96. list.concat(tai_regalloc.dealloc(r.reghi));
  97. end;
  98. procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);
  99. var
  100. tmpreg: tregister;
  101. tmpref: treference;
  102. begin
  103. if target_info.endian = endian_big then
  104. begin
  105. tmpreg:=reg.reglo;
  106. reg.reglo:=reg.reghi;
  107. reg.reghi:=tmpreg;
  108. end;
  109. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
  110. tmpref := ref;
  111. inc(tmpref.offset,4);
  112. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  113. end;
  114. procedure tcg64f32.a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);
  115. var
  116. tmpref: treference;
  117. begin
  118. if target_info.endian = endian_big then
  119. swap_qword(value);
  120. cg.a_load_const_ref(list,OS_32,lo(value),ref);
  121. tmpref := ref;
  122. inc(tmpref.offset,4);
  123. cg.a_load_const_ref(list,OS_32,hi(value),tmpref);
  124. end;
  125. procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64{$ifdef newra};delete:boolean{$endif});
  126. var
  127. tmpreg: tregister;
  128. tmpref: treference;
  129. got_scratch: boolean;
  130. begin
  131. if target_info.endian = endian_big then
  132. begin
  133. tmpreg := reg.reglo;
  134. reg.reglo := reg.reghi;
  135. reg.reghi := tmpreg;
  136. end;
  137. got_scratch:=false;
  138. tmpref := ref;
  139. if (tmpref.base.number=reg.reglo.number) then
  140. begin
  141. {$ifdef newra}
  142. tmpreg:=rg.getaddressregister(list);
  143. {$else}
  144. tmpreg := cg.get_scratch_reg_address(list);
  145. {$endif}
  146. got_scratch:=true;
  147. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  148. tmpref.base:=tmpreg;
  149. end
  150. else
  151. { this works only for the i386, thus the i386 needs to override }
  152. { this method and this method must be replaced by a more generic }
  153. { implementation FK }
  154. if (tmpref.index.number=reg.reglo.number) then
  155. begin
  156. {$ifdef newra}
  157. tmpreg:=rg.getaddressregister(list);
  158. {$else}
  159. tmpreg:=cg.get_scratch_reg_address(list);
  160. {$endif}
  161. got_scratch:=true;
  162. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
  163. tmpref.index:=tmpreg;
  164. end;
  165. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  166. inc(tmpref.offset,4);
  167. {$ifdef newra}
  168. if delete then
  169. begin
  170. tg.ungetiftemp(list,tmpref);
  171. reference_release(list,tmpref);
  172. end;
  173. {$endif}
  174. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  175. {$ifdef newra}
  176. if got_scratch then
  177. rg.ungetregisterint(list,tmpreg);
  178. {$else}
  179. if got_scratch then
  180. cg.free_scratch_reg(list,tmpreg);
  181. {$endif}
  182. end;
  183. procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64{$ifdef newra};delete:boolean{$endif});
  184. begin
  185. {$ifdef newra}
  186. if delete then
  187. rg.ungetregisterint(list,regsrc.reglo);
  188. {$endif}
  189. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
  190. {$ifdef newra}
  191. if delete then
  192. rg.ungetregisterint(list,regsrc.reghi);
  193. {$endif}
  194. cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
  195. end;
  196. procedure tcg64f32.a_load64_const_reg(list : taasmoutput;value : qword;reg : tregister64);
  197. begin
  198. cg.a_load_const_reg(list,OS_32,lo(value),reg.reglo);
  199. cg.a_load_const_reg(list,OS_32,hi(value),reg.reghi);
  200. end;
  201. procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64{$ifdef newra};delete :boolean{$endif});
  202. begin
  203. case l.loc of
  204. LOC_REFERENCE, LOC_CREFERENCE:
  205. a_load64_ref_reg(list,l.reference,reg{$ifdef newra},delete{$endif});
  206. LOC_REGISTER,LOC_CREGISTER:
  207. a_load64_reg_reg(list,l.register64,reg{$ifdef newra},delete{$endif});
  208. LOC_CONSTANT :
  209. a_load64_const_reg(list,l.valueqword,reg);
  210. else
  211. internalerror(200112292);
  212. end;
  213. end;
  214. procedure tcg64f32.a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);
  215. begin
  216. case l.loc of
  217. LOC_REGISTER,LOC_CREGISTER:
  218. a_load64_reg_ref(list,l.reg64,ref);
  219. LOC_CONSTANT :
  220. a_load64_const_ref(list,l.valueqword,ref);
  221. else
  222. internalerror(200203288);
  223. end;
  224. end;
  225. procedure tcg64f32.a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);
  226. begin
  227. case l.loc of
  228. LOC_REFERENCE, LOC_CREFERENCE:
  229. a_load64_const_ref(list,value,l.reference);
  230. LOC_REGISTER,LOC_CREGISTER:
  231. a_load64_const_reg(list,value,l.reg64);
  232. else
  233. internalerror(200112293);
  234. end;
  235. end;
  236. procedure tcg64f32.a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);
  237. begin
  238. case l.loc of
  239. LOC_REFERENCE, LOC_CREFERENCE:
  240. a_load64_reg_ref(list,reg,l.reference);
  241. LOC_REGISTER,LOC_CREGISTER:
  242. a_load64_reg_reg(list,reg,l.register64{$ifdef newra},false{$endif});
  243. else
  244. internalerror(200112293);
  245. end;
  246. end;
  247. procedure tcg64f32.a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
  248. var
  249. tmpref: treference;
  250. begin
  251. if target_info.endian = endian_big then
  252. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  253. else
  254. begin
  255. tmpref := ref;
  256. inc(tmpref.offset,4);
  257. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  258. end;
  259. end;
  260. procedure tcg64f32.a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
  261. var
  262. tmpref: treference;
  263. begin
  264. if target_info.endian = endian_little then
  265. cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
  266. else
  267. begin
  268. tmpref := ref;
  269. inc(tmpref.offset,4);
  270. cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
  271. end;
  272. end;
  273. procedure tcg64f32.a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
  274. var
  275. tmpref: treference;
  276. begin
  277. if target_info.endian = endian_big then
  278. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  279. else
  280. begin
  281. tmpref := ref;
  282. inc(tmpref.offset,4);
  283. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  284. end;
  285. end;
  286. procedure tcg64f32.a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
  287. var
  288. tmpref: treference;
  289. begin
  290. if target_info.endian = endian_little then
  291. cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
  292. else
  293. begin
  294. tmpref := ref;
  295. inc(tmpref.offset,4);
  296. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
  297. end;
  298. end;
  299. procedure tcg64f32.a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  300. begin
  301. case l.loc of
  302. LOC_REFERENCE,
  303. LOC_CREFERENCE :
  304. a_load64low_ref_reg(list,l.reference,reg);
  305. LOC_REGISTER :
  306. cg.a_load_reg_reg(list,OS_32,OS_32,l.registerlow,reg);
  307. LOC_CONSTANT :
  308. cg.a_load_const_reg(list,OS_32,lo(l.valueqword),reg);
  309. else
  310. internalerror(200203244);
  311. end;
  312. end;
  313. procedure tcg64f32.a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
  314. begin
  315. case l.loc of
  316. LOC_REFERENCE,
  317. LOC_CREFERENCE :
  318. a_load64high_ref_reg(list,l.reference,reg);
  319. LOC_REGISTER :
  320. cg.a_load_reg_reg(list,OS_32,OS_32,l.registerhigh,reg);
  321. LOC_CONSTANT :
  322. cg.a_load_const_reg(list,OS_32,hi(l.valueqword),reg);
  323. else
  324. internalerror(200203244);
  325. end;
  326. end;
  327. procedure tcg64f32.a_op64_const_loc(list : taasmoutput;op:TOpCG;value : qword;const l: tlocation);
  328. begin
  329. case l.loc of
  330. LOC_REFERENCE, LOC_CREFERENCE:
  331. a_op64_const_ref(list,op,value,l.reference);
  332. LOC_REGISTER,LOC_CREGISTER:
  333. a_op64_const_reg(list,op,value,l.register64);
  334. else
  335. internalerror(200203292);
  336. end;
  337. end;
  338. procedure tcg64f32.a_op64_reg_loc(list : taasmoutput;op:TOpCG;reg : tregister64;const l : tlocation);
  339. begin
  340. case l.loc of
  341. LOC_REFERENCE, LOC_CREFERENCE:
  342. a_op64_reg_ref(list,op,reg,l.reference);
  343. LOC_REGISTER,LOC_CREGISTER:
  344. a_op64_reg_reg(list,op,reg,l.register64);
  345. else
  346. internalerror(2002032422);
  347. end;
  348. end;
  349. procedure tcg64f32.a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reg : tregister64);
  350. begin
  351. case l.loc of
  352. LOC_REFERENCE, LOC_CREFERENCE:
  353. a_op64_ref_reg(list,op,l.reference,reg);
  354. LOC_REGISTER,LOC_CREGISTER:
  355. a_op64_reg_reg(list,op,l.register64,reg);
  356. LOC_CONSTANT :
  357. a_op64_const_reg(list,op,l.valueqword,reg);
  358. else
  359. internalerror(200203242);
  360. end;
  361. end;
  362. procedure tcg64f32.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);
  363. var
  364. tempreg: tregister64;
  365. begin
  366. {$ifdef newra}
  367. tempreg.reghi:=rg.getregisterint(list,OS_INT);
  368. tempreg.reglo:=rg.getregisterint(list,OS_INT);
  369. {$else}
  370. tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
  371. tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
  372. {$endif}
  373. a_load64_ref_reg(list,ref,tempreg{$ifdef newra},false{$endif});
  374. a_op64_reg_reg(list,op,tempreg,reg);
  375. {$ifdef newra}
  376. rg.ungetregisterint(list,tempreg.reglo);
  377. rg.ungetregisterint(list,tempreg.reghi);
  378. {$else}
  379. cg.free_scratch_reg(list,tempreg.reglo);
  380. cg.free_scratch_reg(list,tempreg.reghi);
  381. {$endif}
  382. end;
  383. procedure tcg64f32.a_op64_reg_ref(list : taasmoutput;op:TOpCG;reg : tregister64; const ref: treference);
  384. var
  385. tempreg: tregister64;
  386. begin
  387. {$ifdef newra}
  388. tempreg.reghi:=rg.getregisterint(list,OS_INT);
  389. tempreg.reglo:=rg.getregisterint(list,OS_INT);
  390. {$else}
  391. tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
  392. tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
  393. {$endif}
  394. a_load64_ref_reg(list,ref,tempreg{$ifdef newra},false{$endif});
  395. a_op64_reg_reg(list,op,reg,tempreg);
  396. a_load64_reg_ref(list,tempreg,ref);
  397. {$ifdef newra}
  398. rg.ungetregisterint(list,tempreg.reglo);
  399. rg.ungetregisterint(list,tempreg.reghi);
  400. {$else}
  401. cg.free_scratch_reg(list,tempreg.reglo);
  402. cg.free_scratch_reg(list,tempreg.reghi);
  403. {$endif}
  404. end;
  405. procedure tcg64f32.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : qword;const ref : treference);
  406. var
  407. tempreg: tregister64;
  408. begin
  409. {$ifdef newra}
  410. tempreg.reghi:=rg.getregisterint(list,OS_INT);
  411. tempreg.reglo:=rg.getregisterint(list,OS_INT);
  412. {$else}
  413. tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
  414. tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
  415. {$endif}
  416. a_load64_ref_reg(list,ref,tempreg{$ifdef newra},false{$endif});
  417. a_op64_const_reg(list,op,value,tempreg);
  418. a_load64_reg_ref(list,tempreg,ref);
  419. {$ifdef newra}
  420. rg.ungetregisterint(list,tempreg.reglo);
  421. rg.ungetregisterint(list,tempreg.reghi);
  422. {$else}
  423. cg.free_scratch_reg(list,tempreg.reglo);
  424. cg.free_scratch_reg(list,tempreg.reghi);
  425. {$endif}
  426. end;
  427. procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);
  428. var
  429. tmplochi,tmploclo: tparalocation;
  430. begin
  431. tmplochi:=locpara;
  432. tmploclo:=locpara;
  433. if locpara.size=OS_S64 then
  434. tmplochi.size:=OS_S32
  435. else
  436. tmplochi.size:=OS_32;
  437. tmploclo.size:=OS_32;
  438. case locpara.loc of
  439. LOC_REGISTER:
  440. tmplochi.register:=tmplochi.registerhigh;
  441. { !!! i386 doesn't pass proper locations here
  442. so always take a loc_reference, since that's what it uses (JM)
  443. LOC_REFERENCE:
  444. }
  445. else
  446. if target_info.endian=endian_big then
  447. inc(tmploclo.reference.offset,4)
  448. else
  449. inc(tmplochi.reference.offset,4);
  450. {
  451. else
  452. internalerror(2003042702);
  453. }
  454. end;
  455. cg.a_param_reg(list,OS_32,reg.reghi,tmplochi);
  456. cg.a_param_reg(list,OS_32,reg.reglo,tmploclo);
  457. end;
  458. procedure tcg64f32.a_param64_const(list : taasmoutput;value : qword;const locpara : tparalocation);
  459. var
  460. tmplochi,tmploclo: tparalocation;
  461. begin
  462. tmplochi:=locpara;
  463. tmploclo:=locpara;
  464. if locpara.size=OS_S64 then
  465. tmplochi.size:=OS_S32
  466. else
  467. tmplochi.size:=OS_32;
  468. tmploclo.size:=OS_32;
  469. case locpara.loc of
  470. LOC_REGISTER:
  471. tmplochi.register:=tmplochi.registerhigh;
  472. { !!! i386 doesn't pass proper locations here
  473. so always take a loc_reference, since that's what it uses (JM)
  474. LOC_REFERENCE:
  475. }
  476. else
  477. if target_info.endian=endian_big then
  478. inc(tmploclo.reference.offset,4)
  479. else
  480. inc(tmplochi.reference.offset,4);
  481. {
  482. else
  483. internalerror(2003042702);
  484. }
  485. end;
  486. cg.a_param_const(list,OS_32,hi(value),tmplochi);
  487. cg.a_param_const(list,OS_32,lo(value),tmploclo);
  488. end;
  489. procedure tcg64f32.a_param64_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  490. var
  491. tmprefhi,tmpreflo : treference;
  492. tmploclo,tmplochi : tparalocation;
  493. begin
  494. tmprefhi:=r;
  495. tmpreflo:=r;
  496. tmplochi:=locpara;
  497. tmploclo:=locpara;
  498. if locpara.size=OS_S64 then
  499. tmplochi.size:=OS_S32
  500. else
  501. tmplochi.size:=OS_32;
  502. tmploclo.size:=OS_32;
  503. case locpara.loc of
  504. LOC_REGISTER:
  505. begin
  506. if target_info.endian=endian_big then
  507. inc(tmpreflo.offset,4)
  508. else
  509. inc(tmprefhi.offset,4);
  510. tmplochi.register:=tmplochi.registerhigh;
  511. end;
  512. { !!! i386 doesn't pass proper locations here
  513. so always take a loc_reference, since that's what it uses (JM)
  514. LOC_REFERENCE:
  515. }
  516. else
  517. begin
  518. if target_info.endian=endian_big then
  519. begin
  520. inc(tmpreflo.offset,4);
  521. inc(tmploclo.reference.offset,4);
  522. end
  523. else
  524. begin
  525. inc(tmprefhi.offset,4);
  526. inc(tmplochi.reference.offset,4);
  527. end;
  528. end
  529. {
  530. else
  531. internalerror(2003042701);
  532. }
  533. end;
  534. cg.a_param_ref(list,OS_32,tmprefhi,tmplochi);
  535. cg.a_param_ref(list,OS_32,tmpreflo,tmploclo);
  536. end;
  537. procedure tcg64f32.a_param64_loc(list : taasmoutput;const l:tlocation;const locpara : tparalocation);
  538. begin
  539. case l.loc of
  540. LOC_REGISTER,
  541. LOC_CREGISTER :
  542. a_param64_reg(list,l.register64,locpara);
  543. LOC_CONSTANT :
  544. a_param64_const(list,l.valueqword,locpara);
  545. LOC_CREFERENCE,
  546. LOC_REFERENCE :
  547. a_param64_ref(list,l.reference,locpara);
  548. else
  549. internalerror(200203287);
  550. end;
  551. end;
  552. procedure tcg64f32.g_rangecheck64(list : taasmoutput;const l:tlocation;fromdef,todef:tdef);
  553. var
  554. neglabel,
  555. poslabel,
  556. endlabel: tasmlabel;
  557. hreg : tregister;
  558. hdef : torddef;
  559. opsize : tcgsize;
  560. oldregisterdef: boolean;
  561. from_signed,to_signed: boolean;
  562. got_scratch: boolean;
  563. temploc : tlocation;
  564. begin
  565. from_signed := is_signed(fromdef);
  566. to_signed := is_signed(todef);
  567. if not is_64bit(todef) then
  568. begin
  569. oldregisterdef := registerdef;
  570. registerdef := false;
  571. { get the high dword in a register }
  572. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  573. begin
  574. hreg := l.registerhigh;
  575. got_scratch := false
  576. end
  577. else
  578. begin
  579. {$ifdef newra}
  580. hreg:=rg.getregisterint(list,OS_INT);
  581. {$else}
  582. hreg := cg.get_scratch_reg_int(list,OS_INT);
  583. {$endif}
  584. got_scratch := true;
  585. a_load64high_ref_reg(list,l.reference,hreg);
  586. end;
  587. objectlibrary.getlabel(poslabel);
  588. { check high dword, must be 0 (for positive numbers) }
  589. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
  590. { It can also be $ffffffff, but only for negative numbers }
  591. if from_signed and to_signed then
  592. begin
  593. objectlibrary.getlabel(neglabel);
  594. cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,aword(-1),hreg,neglabel);
  595. end;
  596. { !!! freeing of register should happen directly after compare! (JM) }
  597. {$ifdef newra}
  598. if got_scratch then
  599. rg.ungetregisterint(list,hreg);
  600. {$else}
  601. if got_scratch then
  602. cg.free_scratch_reg(list,hreg);
  603. {$endif}
  604. { For all other values we have a range check error }
  605. cg.a_call_name(list,'FPC_RANGEERROR');
  606. { if the high dword = 0, the low dword can be considered a }
  607. { simple cardinal }
  608. cg.a_label(list,poslabel);
  609. hdef:=torddef.create(u32bit,0,cardinal($ffffffff));
  610. { no use in calling just "g_rangecheck" since that one will }
  611. { simply call the inherited method too (JM) }
  612. location_copy(temploc,l);
  613. temploc.size:=OS_32;
  614. cg.g_rangecheck(list,temploc,hdef,todef);
  615. hdef.free;
  616. if from_signed and to_signed then
  617. begin
  618. objectlibrary.getlabel(endlabel);
  619. cg.a_jmp_always(list,endlabel);
  620. { if the high dword = $ffffffff, then the low dword (when }
  621. { considered as a longint) must be < 0 }
  622. cg.a_label(list,neglabel);
  623. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  624. begin
  625. hreg := l.registerlow;
  626. got_scratch := false
  627. end
  628. else
  629. begin
  630. {$ifdef newra}
  631. hreg:=rg.getregisterint(list,OS_INT);
  632. {$else}
  633. hreg := cg.get_scratch_reg_int(list,OS_INT);
  634. {$endif}
  635. got_scratch := true;
  636. a_load64low_ref_reg(list,l.reference,hreg);
  637. end;
  638. { get a new neglabel (JM) }
  639. objectlibrary.getlabel(neglabel);
  640. cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
  641. { !!! freeing of register should happen directly after compare! (JM) }
  642. {$ifdef newra}
  643. if got_scratch then
  644. rg.ungetregisterint(list,hreg);
  645. {$else}
  646. if got_scratch then
  647. cg.free_scratch_reg(list,hreg);
  648. {$endif}
  649. cg.a_call_name(list,'FPC_RANGEERROR');
  650. { if we get here, the 64bit value lies between }
  651. { longint($80000000) and -1 (JM) }
  652. cg.a_label(list,neglabel);
  653. hdef:=torddef.create(s32bit,longint($80000000),-1);
  654. location_copy(temploc,l);
  655. temploc.size:=OS_32;
  656. cg.g_rangecheck(list,temploc,hdef,todef);
  657. hdef.free;
  658. cg.a_label(list,endlabel);
  659. end;
  660. registerdef := oldregisterdef;
  661. end
  662. else
  663. { todef = 64bit int }
  664. { no 64bit subranges supported, so only a small check is necessary }
  665. { if both are signed or both are unsigned, no problem! }
  666. if (from_signed xor to_signed) and
  667. { also not if the fromdef is unsigned and < 64bit, since that will }
  668. { always fit in a 64bit int (todef is 64bit) }
  669. (from_signed or
  670. (torddef(fromdef).typ = u64bit)) then
  671. begin
  672. { in all cases, there is only a problem if the higest bit is set }
  673. if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
  674. begin
  675. if is_64bit(fromdef) then
  676. begin
  677. hreg := l.registerhigh;
  678. opsize := OS_32;
  679. end
  680. else
  681. begin
  682. hreg := l.register;
  683. opsize := def_cgsize(fromdef);
  684. end;
  685. got_scratch := false;
  686. end
  687. else
  688. begin
  689. {$ifdef newra}
  690. hreg:=rg.getregisterint(list,OS_INT);
  691. {$else}
  692. hreg := cg.get_scratch_reg_int(list,OS_INT);
  693. {$endif}
  694. got_scratch := true;
  695. opsize := def_cgsize(fromdef);
  696. if opsize in [OS_64,OS_S64] then
  697. a_load64high_ref_reg(list,l.reference,hreg)
  698. else
  699. cg.a_load_ref_reg(list,opsize,OS_INT,l.reference,hreg);
  700. end;
  701. objectlibrary.getlabel(poslabel);
  702. cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
  703. { !!! freeing of register should happen directly after compare! (JM) }
  704. {$ifdef newra}
  705. if got_scratch then
  706. rg.ungetregisterint(list,hreg);
  707. {$else}
  708. if got_scratch then
  709. cg.free_scratch_reg(list,hreg);
  710. {$endif}
  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: taasmoutput; var op: topcg; var a : qword; var reg: tregister64): boolean;
  716. var
  717. lowvalue, highvalue : cardinal;
  718. hreg: tregister;
  719. begin
  720. lowvalue := cardinal(a);
  721. highvalue:= 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 <> high(cardinal) then
  733. cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
  734. if highvalue <> high(cardinal) 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. (*
  807. procedure int64f32_assignment_int64_reg(p : passignmentnode);
  808. begin
  809. end;
  810. begin
  811. p2_assignment:=@int64f32_assignement_int64;
  812. *)
  813. end.
  814. {
  815. $Log$
  816. Revision 1.47 2003-06-03 21:11:09 peter
  817. * cg.a_load_* get a from and to size specifier
  818. * makeregsize only accepts newregister
  819. * i386 uses generic tcgnotnode,tcgunaryminus
  820. Revision 1.46 2003/06/03 13:01:59 daniel
  821. * Register allocator finished
  822. Revision 1.45 2003/06/01 21:38:06 peter
  823. * getregisterfpu size parameter added
  824. * op_const_reg size parameter added
  825. * sparc updates
  826. Revision 1.44 2003/05/14 19:31:37 jonas
  827. * fixed a_param64_reg
  828. Revision 1.43 2003/04/27 14:48:09 jonas
  829. * fixed Florian's quick hack :)
  830. * fixed small bug 64bit range checking code
  831. Revision 1.42 2003/04/27 09:10:49 florian
  832. * quick fix for param64 for intel
  833. Revision 1.41 2003/04/27 08:23:51 florian
  834. * fixed parameter passing for 64 bit ints
  835. Revision 1.40 2003/04/23 20:16:03 peter
  836. + added currency support based on int64
  837. + is_64bit for use in cg units instead of is_64bitint
  838. * removed cgmessage from n386add, replace with internalerrors
  839. Revision 1.39 2003/04/22 10:09:34 daniel
  840. + Implemented the actual register allocator
  841. + Scratch registers unavailable when new register allocator used
  842. + maybe_save/maybe_restore unavailable when new register allocator used
  843. Revision 1.38 2003/04/07 08:52:58 jonas
  844. * fixed compiling error
  845. Revision 1.37 2003/04/07 08:45:09 jonas
  846. + generic a_op64_reg_ref implementation
  847. Revision 1.36 2003/03/28 19:16:56 peter
  848. * generic constructor working for i386
  849. * remove fixed self register
  850. * esi added as address register for i386
  851. Revision 1.35 2003/02/19 22:00:14 daniel
  852. * Code generator converted to new register notation
  853. - Horribily outdated todo.txt removed
  854. Revision 1.34 2003/01/08 18:43:56 daniel
  855. * Tregister changed into a record
  856. Revision 1.33 2003/01/05 13:36:53 florian
  857. * x86-64 compiles
  858. + very basic support for float128 type (x86-64 only)
  859. Revision 1.32 2002/11/25 17:43:16 peter
  860. * splitted defbase in defutil,symutil,defcmp
  861. * merged isconvertable and is_equal into compare_defs(_ext)
  862. * made operator search faster by walking the list only once
  863. Revision 1.31 2002/10/05 12:43:23 carl
  864. * fixes for Delphi 6 compilation
  865. (warning : Some features do not work under Delphi)
  866. Revision 1.30 2002/09/17 18:54:01 jonas
  867. * a_load_reg_reg() now has two size parameters: source and dest. This
  868. allows some optimizations on architectures that don't encode the
  869. register size in the register name.
  870. Revision 1.29 2002/09/10 21:24:38 jonas
  871. * fixed a_param64_ref
  872. Revision 1.28 2002/09/07 15:25:00 peter
  873. * old logs removed and tabs fixed
  874. Revision 1.27 2002/08/19 18:17:47 carl
  875. + optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
  876. * more fixes to m68k for 64-bit operations
  877. Revision 1.26 2002/08/17 22:09:43 florian
  878. * result type handling in tcgcal.pass_2 overhauled
  879. * better tnode.dowrite
  880. * some ppc stuff fixed
  881. Revision 1.25 2002/08/14 18:41:47 jonas
  882. - remove valuelow/valuehigh fields from tlocation, because they depend
  883. on the endianess of the host operating system -> difficult to get
  884. right. Use lo/hi(location.valueqword) instead (remember to use
  885. valueqword and not value!!)
  886. Revision 1.24 2002/08/11 14:32:26 peter
  887. * renamed current_library to objectlibrary
  888. Revision 1.23 2002/08/11 13:24:11 peter
  889. * saving of asmsymbols in ppu supported
  890. * asmsymbollist global is removed and moved into a new class
  891. tasmlibrarydata that will hold the info of a .a file which
  892. corresponds with a single module. Added librarydata to tmodule
  893. to keep the library info stored for the module. In the future the
  894. objectfiles will also be stored to the tasmlibrarydata class
  895. * all getlabel/newasmsymbol and friends are moved to the new class
  896. Revision 1.22 2002/07/28 15:57:15 jonas
  897. * fixed a_load64_const_reg() for big endian systems
  898. Revision 1.21 2002/07/20 11:57:52 florian
  899. * types.pas renamed to defbase.pas because D6 contains a types
  900. unit so this would conflicts if D6 programms are compiled
  901. + Willamette/SSE2 instructions to assembler added
  902. Revision 1.20 2002/07/12 10:14:26 jonas
  903. * some big-endian fixes
  904. Revision 1.19 2002/07/11 07:23:17 jonas
  905. + generic implementations of a_op64_ref_reg() and a_op64_const_ref()
  906. (only works for processors with >2 scratch registers)
  907. Revision 1.18 2002/07/10 11:12:44 jonas
  908. * fixed a_op64_const_loc()
  909. Revision 1.17 2002/07/07 09:52:32 florian
  910. * powerpc target fixed, very simple units can be compiled
  911. * some basic stuff for better callparanode handling, far from being finished
  912. Revision 1.16 2002/07/01 18:46:21 peter
  913. * internal linker
  914. * reorganized aasm layer
  915. Revision 1.15 2002/07/01 16:23:52 peter
  916. * cg64 patch
  917. * basics for currency
  918. * asnode updates for class and interface (not finished)
  919. Revision 1.14 2002/05/20 13:30:40 carl
  920. * bugfix of hdisponen (base must be set, not index)
  921. * more portability fixes
  922. Revision 1.13 2002/05/18 13:34:05 peter
  923. * readded missing revisions
  924. Revision 1.12 2002/05/16 19:46:35 carl
  925. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  926. + try to fix temp allocation (still in ifdef)
  927. + generic constructor calls
  928. + start of tassembler / tmodulebase class cleanup
  929. Revision 1.10 2002/05/12 16:53:04 peter
  930. * moved entry and exitcode to ncgutil and cgobj
  931. * foreach gets extra argument for passing local data to the
  932. iterator function
  933. * -CR checks also class typecasts at runtime by changing them
  934. into as
  935. * fixed compiler to cycle with the -CR option
  936. * fixed stabs with elf writer, finally the global variables can
  937. be watched
  938. * removed a lot of routines from cga unit and replaced them by
  939. calls to cgobj
  940. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  941. u32bit then the other is typecasted also to u32bit without giving
  942. a rangecheck warning/error.
  943. * fixed pascal calling method with reversing also the high tree in
  944. the parast, detected by tcalcst3 test
  945. Revision 1.9 2002/04/25 20:16:38 peter
  946. * moved more routines from cga/n386util
  947. Revision 1.8 2002/04/21 15:28:51 carl
  948. * a_jmp_cond -> a_jmp_always
  949. Revision 1.7 2002/04/07 13:21:18 carl
  950. + more documentation
  951. }