n386util.pas 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Helper routines for the i386 code generator
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit n386util;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. symtype,node;
  23. function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
  24. function maybe_pushfpu(needed : byte;p : tnode) : boolean;
  25. {$ifdef TEMPS_NOT_PUSH}
  26. function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
  27. {$endif TEMPS_NOT_PUSH}
  28. procedure restore(p : tnode;isint64 : boolean);
  29. {$ifdef TEMPS_NOT_PUSH}
  30. procedure restorefromtemp(p : tnode;isint64 : boolean);
  31. {$endif TEMPS_NOT_PUSH}
  32. procedure pushsetelement(p : tnode);
  33. procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
  34. para_offset:longint;alignment : longint);
  35. procedure loadshortstring(source,dest : tnode);
  36. procedure loadlongstring(p:tbinarynode);
  37. procedure loadansi2short(source,dest : tnode);
  38. procedure loadwide2short(source,dest : tnode);
  39. procedure loadinterfacecom(p: tbinarynode);
  40. procedure emitoverflowcheck(p:tnode);
  41. procedure firstcomplex(p : tbinarynode);
  42. implementation
  43. uses
  44. globtype,globals,systems,verbose,
  45. cutils,
  46. aasm,cpubase,cpuasm,cpuinfo,
  47. symconst,symbase,symdef,symsym,symtable,
  48. {$ifdef GDB}
  49. gdb,
  50. {$endif GDB}
  51. types,
  52. ncon,nld,
  53. pass_1,pass_2,
  54. cgbase,tgcpu,temp_gen,
  55. cga,regvars;
  56. {*****************************************************************************
  57. Emit Push Functions
  58. *****************************************************************************}
  59. function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
  60. var
  61. pushed : boolean;
  62. {hregister : tregister; }
  63. {$ifdef TEMPS_NOT_PUSH}
  64. href : treference;
  65. {$endif TEMPS_NOT_PUSH}
  66. begin
  67. if p.location.loc = LOC_CREGISTER then
  68. begin
  69. maybe_push := true;
  70. exit;
  71. end;
  72. if needed>usablereg32 then
  73. begin
  74. if (p.location.loc=LOC_REGISTER) then
  75. begin
  76. if isint64 then
  77. begin
  78. {$ifdef TEMPS_NOT_PUSH}
  79. gettempofsizereference(href,8);
  80. p.temp_offset:=href.offset;
  81. href.offset:=href.offset+4;
  82. exprasmList.concat(Taicpu.Op_reg(A_MOV,S_L,p.location.registerhigh,href));
  83. href.offset:=href.offset-4;
  84. {$else TEMPS_NOT_PUSH}
  85. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.location.registerhigh));
  86. {$endif TEMPS_NOT_PUSH}
  87. ungetregister32(p.location.registerhigh);
  88. end
  89. {$ifdef TEMPS_NOT_PUSH}
  90. else
  91. begin
  92. gettempofsizereference(href,4);
  93. p.temp_offset:=href.offset;
  94. end
  95. {$endif TEMPS_NOT_PUSH}
  96. ;
  97. pushed:=true;
  98. {$ifdef TEMPS_NOT_PUSH}
  99. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,p.location.register,href));
  100. {$else TEMPS_NOT_PUSH}
  101. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.location.register));
  102. {$endif TEMPS_NOT_PUSH}
  103. ungetregister32(p.location.register);
  104. end
  105. else if (p.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  106. ((p.location.reference.base<>R_NO) or
  107. (p.location.reference.index<>R_NO)
  108. ) then
  109. begin
  110. del_reference(p.location.reference);
  111. getexplicitregister32(R_EDI);
  112. emit_ref_reg(A_LEA,S_L,newreference(p.location.reference),R_EDI);
  113. {$ifdef TEMPS_NOT_PUSH}
  114. gettempofsizereference(href,4);
  115. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
  116. p.temp_offset:=href.offset;
  117. {$else TEMPS_NOT_PUSH}
  118. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,R_EDI));
  119. {$endif TEMPS_NOT_PUSH}
  120. ungetregister32(R_EDI);
  121. pushed:=true;
  122. end
  123. else pushed:=false;
  124. end
  125. else pushed:=false;
  126. maybe_push:=pushed;
  127. end;
  128. function maybe_pushfpu(needed : byte;p : tnode) : boolean;
  129. begin
  130. if needed>=maxfpuregs then
  131. begin
  132. if p.location.loc = LOC_FPU then
  133. begin
  134. emit_to_mem(p.location,p.resulttype.def);
  135. maybe_pushfpu:=true;
  136. end
  137. else
  138. maybe_pushfpu:=false;
  139. end
  140. else
  141. maybe_pushfpu:=false;
  142. end;
  143. {$ifdef TEMPS_NOT_PUSH}
  144. function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
  145. var
  146. pushed : boolean;
  147. href : treference;
  148. begin
  149. if needed>usablereg32 then
  150. begin
  151. if (p^.location.loc=LOC_REGISTER) then
  152. begin
  153. if isint64(p^.resulttype.def) then
  154. begin
  155. gettempofsizereference(href,8);
  156. p^.temp_offset:=href.offset;
  157. href.offset:=href.offset+4;
  158. exprasmList.concat(Taicpu.Op_reg(A_MOV,S_L,p^.location.registerhigh,href));
  159. href.offset:=href.offset-4;
  160. ungetregister32(p^.location.registerhigh);
  161. end
  162. else
  163. begin
  164. gettempofsizereference(href,4);
  165. p^.temp_offset:=href.offset;
  166. end;
  167. pushed:=true;
  168. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,p^.location.register,href));
  169. ungetregister32(p^.location.register);
  170. end
  171. else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  172. ((p^.location.reference.base<>R_NO) or
  173. (p^.location.reference.index<>R_NO)
  174. ) then
  175. begin
  176. del_reference(p^.location.reference);
  177. getexplicitregister32(R_EDI);
  178. emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
  179. R_EDI);
  180. gettempofsizereference(href,4);
  181. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
  182. ungetregister32(R_EDI);
  183. p^.temp_offset:=href.offset;
  184. pushed:=true;
  185. end
  186. else pushed:=false;
  187. end
  188. else pushed:=false;
  189. maybe_push:=pushed;
  190. end;
  191. {$endif TEMPS_NOT_PUSH}
  192. procedure restore(p : tnode;isint64 : boolean);
  193. var
  194. hregister : tregister;
  195. {$ifdef TEMPS_NOT_PUSH}
  196. href : treference;
  197. {$endif TEMPS_NOT_PUSH}
  198. begin
  199. if p.location.loc = LOC_CREGISTER then
  200. begin
  201. load_regvar_reg(exprasmlist,p.location.register);
  202. exit;
  203. end;
  204. hregister:=getregisterint;
  205. {$ifdef TEMPS_NOT_PUSH}
  206. reset_reference(href);
  207. href.base:=procinfo^.frame_pointer;
  208. href.offset:=p.temp_offset;
  209. emit_ref_reg(A_MOV,S_L,href,hregister);
  210. {$else TEMPS_NOT_PUSH}
  211. exprasmList.concat(Taicpu.Op_reg(A_POP,S_L,hregister));
  212. {$endif TEMPS_NOT_PUSH}
  213. if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  214. begin
  215. p.location.register:=hregister;
  216. if isint64 then
  217. begin
  218. p.location.registerhigh:=getregisterint;
  219. {$ifdef TEMPS_NOT_PUSH}
  220. href.offset:=p.temp_offset+4;
  221. emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
  222. { set correctly for release ! }
  223. href.offset:=p.temp_offset;
  224. {$else TEMPS_NOT_PUSH}
  225. exprasmList.concat(Taicpu.Op_reg(A_POP,S_L,p.location.registerhigh));
  226. {$endif TEMPS_NOT_PUSH}
  227. end;
  228. end
  229. else
  230. begin
  231. reset_reference(p.location.reference);
  232. { any reasons why this was moved into the index register ? }
  233. { normally usage of base register is much better (FK) }
  234. p.location.reference.base:=hregister;
  235. { Why is this done? We can never be sure about p.left
  236. because otherwise secondload fails !!!
  237. set_location(p.left^.location,p.location);}
  238. end;
  239. {$ifdef TEMPS_NOT_PUSH}
  240. ungetiftemp(href);
  241. {$endif TEMPS_NOT_PUSH}
  242. end;
  243. {$ifdef TEMPS_NOT_PUSH}
  244. procedure restorefromtemp(p : tnode;isint64 : boolean);
  245. var
  246. hregister : tregister;
  247. href : treference;
  248. begin
  249. hregister:=getregisterint;
  250. reset_reference(href);
  251. href.base:=procinfo^.frame_pointer;
  252. href.offset:=p.temp_offset;
  253. emit_ref_reg(A_MOV,S_L,href,hregister);
  254. if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  255. begin
  256. p.location.register:=hregister;
  257. if isint64 then
  258. begin
  259. p.location.registerhigh:=getregisterint;
  260. href.offset:=p.temp_offset+4;
  261. emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
  262. { set correctly for release ! }
  263. href.offset:=p.temp_offset;
  264. end;
  265. end
  266. else
  267. begin
  268. reset_reference(p.location.reference);
  269. p.location.reference.base:=hregister;
  270. { Why is this done? We can never be sure about p^.left
  271. because otherwise secondload fails PM
  272. set_location(p^.left^.location,p^.location);}
  273. end;
  274. ungetiftemp(href);
  275. end;
  276. {$endif TEMPS_NOT_PUSH}
  277. procedure pushsetelement(p : tnode);
  278. var
  279. hr,hr16,hr32 : tregister;
  280. begin
  281. { copy the element on the stack, slightly complicated }
  282. if p.nodetype=ordconstn then
  283. begin
  284. if aktalignment.paraalign=4 then
  285. exprasmList.concat(Taicpu.Op_const(A_PUSH,S_L,tordconstnode(p).value))
  286. else
  287. exprasmList.concat(Taicpu.Op_const(A_PUSH,S_W,tordconstnode(p).value));
  288. end
  289. else
  290. begin
  291. case p.location.loc of
  292. LOC_REGISTER,
  293. LOC_CREGISTER :
  294. begin
  295. hr:=p.location.register;
  296. case hr of
  297. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  298. begin
  299. hr16:=reg32toreg16(hr);
  300. hr32:=hr;
  301. end;
  302. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  303. begin
  304. hr16:=hr;
  305. hr32:=reg16toreg32(hr);
  306. end;
  307. R_AL,R_BL,R_CL,R_DL :
  308. begin
  309. hr16:=reg8toreg16(hr);
  310. hr32:=reg8toreg32(hr);
  311. end;
  312. end;
  313. if aktalignment.paraalign=4 then
  314. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,hr32))
  315. else
  316. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_W,hr16));
  317. ungetregister32(hr32);
  318. end;
  319. else
  320. begin
  321. { you can't push more bytes than the size of the element, }
  322. { because this may cross a page boundary and you'll get a }
  323. { sigsegv (JM) }
  324. emit_push_mem_size(p.location.reference,1);
  325. del_reference(p.location.reference);
  326. end;
  327. end;
  328. end;
  329. end;
  330. procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
  331. para_offset:longint;alignment : longint);
  332. var
  333. tempreference : treference;
  334. r : preference;
  335. opsize : topsize;
  336. op : tasmop;
  337. hreg : tregister;
  338. size : longint;
  339. hlabel : tasmlabel;
  340. begin
  341. case p.location.loc of
  342. LOC_REGISTER,
  343. LOC_CREGISTER:
  344. begin
  345. if p.resulttype.def.size=8 then
  346. begin
  347. inc(pushedparasize,8);
  348. if inlined then
  349. begin
  350. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  351. exprasmlist.concat(taicpu.op_reg_ref(A_MOV,S_L,p.location.registerlow,r));
  352. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
  353. exprasmlist.concat(taicpu.op_reg_ref(A_MOV,S_L,p.location.registerhigh,r));
  354. end
  355. else
  356. begin
  357. exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,p.location.registerhigh));
  358. exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,p.location.registerlow));
  359. end;
  360. ungetregister32(p.location.registerhigh);
  361. ungetregister32(p.location.registerlow);
  362. end
  363. else case p.location.register of
  364. R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
  365. R_EDI,R_ESP,R_EBP :
  366. begin
  367. inc(pushedparasize,4);
  368. if inlined then
  369. begin
  370. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  371. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,p.location.register,r));
  372. end
  373. else
  374. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.location.register));
  375. ungetregister32(p.location.register);
  376. end;
  377. R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
  378. begin
  379. if alignment=4 then
  380. begin
  381. opsize:=S_L;
  382. hreg:=reg16toreg32(p.location.register);
  383. inc(pushedparasize,4);
  384. end
  385. else
  386. begin
  387. opsize:=S_W;
  388. hreg:=p.location.register;
  389. inc(pushedparasize,2);
  390. end;
  391. if inlined then
  392. begin
  393. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  394. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
  395. end
  396. else
  397. exprasmList.concat(Taicpu.Op_reg(A_PUSH,opsize,hreg));
  398. ungetregister32(reg16toreg32(p.location.register));
  399. end;
  400. R_AL,R_BL,R_CL,R_DL:
  401. begin
  402. if alignment=4 then
  403. begin
  404. opsize:=S_L;
  405. hreg:=reg8toreg32(p.location.register);
  406. inc(pushedparasize,4);
  407. end
  408. else
  409. begin
  410. opsize:=S_W;
  411. hreg:=reg8toreg16(p.location.register);
  412. inc(pushedparasize,2);
  413. end;
  414. { we must push always 16 bit }
  415. if inlined then
  416. begin
  417. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  418. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
  419. end
  420. else
  421. exprasmList.concat(Taicpu.Op_reg(A_PUSH,opsize,hreg));
  422. ungetregister32(reg8toreg32(p.location.register));
  423. end;
  424. else internalerror(1899);
  425. end;
  426. end;
  427. LOC_FPU:
  428. begin
  429. size:=align(tfloatdef(p.resulttype.def).size,alignment);
  430. inc(pushedparasize,size);
  431. if not inlined then
  432. emit_const_reg(A_SUB,S_L,size,R_ESP);
  433. {$ifdef GDB}
  434. if (cs_debuginfo in aktmoduleswitches) and
  435. (exprasmList.first=exprasmList.last) then
  436. exprasmList.concat(Tai_force_line.Create);
  437. {$endif GDB}
  438. r:=new_reference(R_ESP,0);
  439. floatstoreops(tfloatdef(p.resulttype.def).typ,op,opsize);
  440. { this is the easiest case for inlined !! }
  441. if inlined then
  442. begin
  443. r^.base:=procinfo^.framepointer;
  444. r^.offset:=para_offset-pushedparasize;
  445. end;
  446. exprasmList.concat(Taicpu.Op_ref(op,opsize,r));
  447. dec(fpuvaroffset);
  448. end;
  449. LOC_CFPUREGISTER:
  450. begin
  451. exprasmList.concat(Taicpu.Op_reg(A_FLD,S_NO,
  452. correct_fpuregister(p.location.register,fpuvaroffset)));
  453. size:=align(tfloatdef(p.resulttype.def).size,alignment);
  454. inc(pushedparasize,size);
  455. if not inlined then
  456. emit_const_reg(A_SUB,S_L,size,R_ESP);
  457. {$ifdef GDB}
  458. if (cs_debuginfo in aktmoduleswitches) and
  459. (exprasmList.first=exprasmList.last) then
  460. exprasmList.concat(Tai_force_line.Create);
  461. {$endif GDB}
  462. r:=new_reference(R_ESP,0);
  463. floatstoreops(tfloatdef(p.resulttype.def).typ,op,opsize);
  464. { this is the easiest case for inlined !! }
  465. if inlined then
  466. begin
  467. r^.base:=procinfo^.framepointer;
  468. r^.offset:=para_offset-pushedparasize;
  469. end;
  470. exprasmList.concat(Taicpu.Op_ref(op,opsize,r));
  471. end;
  472. LOC_REFERENCE,LOC_MEM:
  473. begin
  474. tempreference:=p.location.reference;
  475. del_reference(p.location.reference);
  476. case p.resulttype.def.deftype of
  477. enumdef,
  478. orddef :
  479. begin
  480. case p.resulttype.def.size of
  481. 8 : begin
  482. inc(pushedparasize,8);
  483. if inlined then
  484. begin
  485. getexplicitregister32(R_EDI);
  486. emit_ref_reg(A_MOV,S_L,
  487. newreference(tempreference),R_EDI);
  488. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  489. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  490. ungetregister32(R_EDI);
  491. getexplicitregister32(R_EDI);
  492. inc(tempreference.offset,4);
  493. emit_ref_reg(A_MOV,S_L,
  494. newreference(tempreference),R_EDI);
  495. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
  496. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  497. ungetregister32(R_EDI);
  498. end
  499. else
  500. begin
  501. inc(tempreference.offset,4);
  502. emit_push_mem(tempreference);
  503. dec(tempreference.offset,4);
  504. emit_push_mem(tempreference);
  505. end;
  506. end;
  507. 4 : begin
  508. inc(pushedparasize,4);
  509. if inlined then
  510. begin
  511. getexplicitregister32(R_EDI);
  512. emit_ref_reg(A_MOV,S_L,
  513. newreference(tempreference),R_EDI);
  514. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  515. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  516. ungetregister32(R_EDI);
  517. end
  518. else
  519. emit_push_mem(tempreference);
  520. end;
  521. 1,2 : begin
  522. if alignment=4 then
  523. begin
  524. opsize:=S_L;
  525. hreg:=R_EDI;
  526. inc(pushedparasize,4);
  527. end
  528. else
  529. begin
  530. opsize:=S_W;
  531. hreg:=R_DI;
  532. inc(pushedparasize,2);
  533. end;
  534. if inlined then
  535. begin
  536. getexplicitregister32(R_EDI);
  537. emit_ref_reg(A_MOV,opsize,
  538. newreference(tempreference),hreg);
  539. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  540. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
  541. ungetregister32(R_EDI);
  542. end
  543. else
  544. emit_push_mem_size(tempreference,p.resulttype.def.size);
  545. end;
  546. else
  547. internalerror(234231);
  548. end;
  549. end;
  550. floatdef :
  551. begin
  552. case tfloatdef(p.resulttype.def).typ of
  553. s32real :
  554. begin
  555. inc(pushedparasize,4);
  556. if inlined then
  557. begin
  558. getexplicitregister32(R_EDI);
  559. emit_ref_reg(A_MOV,S_L,
  560. newreference(tempreference),R_EDI);
  561. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  562. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  563. ungetregister32(R_EDI);
  564. end
  565. else
  566. emit_push_mem(tempreference);
  567. end;
  568. s64real,
  569. s64comp :
  570. begin
  571. inc(pushedparasize,4);
  572. inc(tempreference.offset,4);
  573. if inlined then
  574. begin
  575. getexplicitregister32(R_EDI);
  576. emit_ref_reg(A_MOV,S_L,
  577. newreference(tempreference),R_EDI);
  578. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  579. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  580. ungetregister32(R_EDI);
  581. end
  582. else
  583. emit_push_mem(tempreference);
  584. inc(pushedparasize,4);
  585. dec(tempreference.offset,4);
  586. if inlined then
  587. begin
  588. getexplicitregister32(R_EDI);
  589. emit_ref_reg(A_MOV,S_L,
  590. newreference(tempreference),R_EDI);
  591. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  592. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  593. ungetregister32(R_EDI);
  594. end
  595. else
  596. emit_push_mem(tempreference);
  597. end;
  598. s80real :
  599. begin
  600. inc(pushedparasize,4);
  601. if alignment=4 then
  602. inc(tempreference.offset,8)
  603. else
  604. inc(tempreference.offset,6);
  605. if inlined then
  606. begin
  607. getexplicitregister32(R_EDI);
  608. emit_ref_reg(A_MOV,S_L,
  609. newreference(tempreference),R_EDI);
  610. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  611. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  612. ungetregister32(R_EDI);
  613. end
  614. else
  615. emit_push_mem(tempreference);
  616. dec(tempreference.offset,4);
  617. inc(pushedparasize,4);
  618. if inlined then
  619. begin
  620. getexplicitregister32(R_EDI);
  621. emit_ref_reg(A_MOV,S_L,
  622. newreference(tempreference),R_EDI);
  623. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  624. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  625. ungetregister32(R_EDI);
  626. end
  627. else
  628. emit_push_mem(tempreference);
  629. if alignment=4 then
  630. begin
  631. opsize:=S_L;
  632. hreg:=R_EDI;
  633. inc(pushedparasize,4);
  634. dec(tempreference.offset,4);
  635. end
  636. else
  637. begin
  638. opsize:=S_W;
  639. hreg:=R_DI;
  640. inc(pushedparasize,2);
  641. dec(tempreference.offset,2);
  642. end;
  643. if inlined then
  644. begin
  645. getexplicitregister32(R_EDI);
  646. emit_ref_reg(A_MOV,opsize,
  647. newreference(tempreference),hreg);
  648. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  649. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
  650. ungetregister32(R_EDI);
  651. end
  652. else
  653. exprasmList.concat(Taicpu.Op_ref(A_PUSH,opsize,
  654. newreference(tempreference)));
  655. end;
  656. end;
  657. end;
  658. pointerdef,
  659. procvardef,
  660. classrefdef:
  661. begin
  662. inc(pushedparasize,4);
  663. if inlined then
  664. begin
  665. getexplicitregister32(R_EDI);
  666. emit_ref_reg(A_MOV,S_L,
  667. newreference(tempreference),R_EDI);
  668. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  669. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
  670. ungetregister32(R_EDI);
  671. end
  672. else
  673. emit_push_mem(tempreference);
  674. end;
  675. arraydef,
  676. recorddef,
  677. stringdef,
  678. setdef,
  679. objectdef :
  680. begin
  681. { even some structured types are 32 bit }
  682. if is_widestring(p.resulttype.def) or
  683. is_ansistring(p.resulttype.def) or
  684. is_smallset(p.resulttype.def) or
  685. ((p.resulttype.def.deftype in [recorddef,arraydef]) and
  686. (
  687. (p.resulttype.def.deftype<>arraydef) or not
  688. (tarraydef(p.resulttype.def).IsConstructor or
  689. tarraydef(p.resulttype.def).isArrayOfConst or
  690. is_open_array(p.resulttype.def))
  691. ) and
  692. (p.resulttype.def.size<=4)
  693. ) or
  694. is_class(p.resulttype.def) or
  695. is_interface(p.resulttype.def) then
  696. begin
  697. if (p.resulttype.def.size>2) or
  698. ((alignment=4) and (p.resulttype.def.size>0)) then
  699. begin
  700. inc(pushedparasize,4);
  701. if inlined then
  702. begin
  703. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  704. concatcopy(tempreference,r^,4,false,false);
  705. end
  706. else
  707. emit_push_mem(tempreference);
  708. end
  709. else
  710. begin
  711. if p.resulttype.def.size>0 then
  712. begin
  713. inc(pushedparasize,2);
  714. if inlined then
  715. begin
  716. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  717. concatcopy(tempreference,r^,2,false,false);
  718. end
  719. else
  720. exprasmList.concat(Taicpu.Op_ref(A_PUSH,S_W,newreference(tempreference)));
  721. end;
  722. end;
  723. end
  724. { call by value open array ? }
  725. else if is_cdecl then
  726. begin
  727. { push on stack }
  728. size:=align(p.resulttype.def.size,alignment);
  729. inc(pushedparasize,size);
  730. emit_const_reg(A_SUB,S_L,size,R_ESP);
  731. r:=new_reference(R_ESP,0);
  732. concatcopy(tempreference,r^,size,false,false);
  733. dispose(r);
  734. end
  735. else
  736. internalerror(8954);
  737. end;
  738. else
  739. CGMessage(cg_e_illegal_expression);
  740. end;
  741. end;
  742. LOC_JUMP:
  743. begin
  744. getlabel(hlabel);
  745. if alignment=4 then
  746. begin
  747. opsize:=S_L;
  748. inc(pushedparasize,4);
  749. end
  750. else
  751. begin
  752. opsize:=S_W;
  753. inc(pushedparasize,2);
  754. end;
  755. emitlab(truelabel);
  756. if inlined then
  757. begin
  758. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  759. emit_const_ref(A_MOV,opsize,1,r);
  760. end
  761. else
  762. exprasmList.concat(Taicpu.Op_const(A_PUSH,opsize,1));
  763. emitjmp(C_None,hlabel);
  764. emitlab(falselabel);
  765. if inlined then
  766. begin
  767. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  768. emit_const_ref(A_MOV,opsize,0,r);
  769. end
  770. else
  771. exprasmList.concat(Taicpu.Op_const(A_PUSH,opsize,0));
  772. emitlab(hlabel);
  773. end;
  774. LOC_FLAGS:
  775. begin
  776. if not(R_EAX in unused) then
  777. begin
  778. getexplicitregister32(R_EDI);
  779. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  780. end;
  781. emit_flag2reg(p.location.resflags,R_AL);
  782. emit_reg_reg(A_MOVZX,S_BW,R_AL,R_AX);
  783. if alignment=4 then
  784. begin
  785. opsize:=S_L;
  786. hreg:=R_EAX;
  787. inc(pushedparasize,4);
  788. end
  789. else
  790. begin
  791. opsize:=S_W;
  792. hreg:=R_AX;
  793. inc(pushedparasize,2);
  794. end;
  795. if inlined then
  796. begin
  797. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  798. exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
  799. end
  800. else
  801. exprasmList.concat(Taicpu.Op_reg(A_PUSH,opsize,hreg));
  802. if not(R_EAX in unused) then
  803. begin
  804. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  805. ungetregister32(R_EDI);
  806. end;
  807. end;
  808. {$ifdef SUPPORT_MMX}
  809. LOC_MMXREGISTER,
  810. LOC_CMMXREGISTER:
  811. begin
  812. inc(pushedparasize,8); { was missing !!! (PM) }
  813. emit_const_reg(
  814. A_SUB,S_L,8,R_ESP);
  815. {$ifdef GDB}
  816. if (cs_debuginfo in aktmoduleswitches) and
  817. (exprasmList.first=exprasmList.last) then
  818. exprasmList.concat(Tai_force_line.Create);
  819. {$endif GDB}
  820. if inlined then
  821. begin
  822. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  823. exprasmList.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,
  824. p.location.register,r));
  825. end
  826. else
  827. begin
  828. r:=new_reference(R_ESP,0);
  829. exprasmList.concat(Taicpu.Op_reg_ref(
  830. A_MOVQ,S_NO,p.location.register,r));
  831. end;
  832. end;
  833. {$endif SUPPORT_MMX}
  834. end;
  835. end;
  836. {*****************************************************************************
  837. Emit Functions
  838. *****************************************************************************}
  839. { produces if necessary overflowcode }
  840. procedure emitoverflowcheck(p:tnode);
  841. var
  842. hl : tasmlabel;
  843. begin
  844. if not(cs_check_overflow in aktlocalswitches) then
  845. exit;
  846. getlabel(hl);
  847. if not ((p.resulttype.def.deftype=pointerdef) or
  848. ((p.resulttype.def.deftype=orddef) and
  849. (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  850. bool8bit,bool16bit,bool32bit]))) then
  851. emitjmp(C_NO,hl)
  852. else
  853. emitjmp(C_NB,hl);
  854. emitcall('FPC_OVERFLOW');
  855. emitlab(hl);
  856. end;
  857. { DO NOT RELY on the fact that the tnode is not yet swaped
  858. because of inlining code PM }
  859. procedure firstcomplex(p : tbinarynode);
  860. var
  861. hp : tnode;
  862. begin
  863. { always calculate boolean AND and OR from left to right }
  864. if (p.nodetype in [orn,andn]) and
  865. (p.left.resulttype.def.deftype=orddef) and
  866. (torddef(p.left.resulttype.def).typ in [bool8bit,bool16bit,bool32bit]) then
  867. begin
  868. { p.swaped:=false}
  869. if nf_swaped in p.flags then
  870. internalerror(234234);
  871. end
  872. else
  873. if (((p.location.loc=LOC_FPU) and
  874. (p.right.registersfpu > p.left.registersfpu)) or
  875. ((((p.left.registersfpu = 0) and
  876. (p.right.registersfpu = 0)) or
  877. (p.location.loc<>LOC_FPU)) and
  878. (p.left.registers32<p.right.registers32))) and
  879. { the following check is appropriate, because all }
  880. { 4 registers are rarely used and it is thereby }
  881. { achieved that the extra code is being dropped }
  882. { by exchanging not commutative operators }
  883. (p.right.registers32<=4) then
  884. begin
  885. hp:=p.left;
  886. p.left:=p.right;
  887. p.right:=hp;
  888. if nf_swaped in p.flags then
  889. exclude(p.flags,nf_swaped)
  890. else
  891. include(p.flags,nf_swaped);
  892. end;
  893. {else
  894. p.swaped:=false; do not modify }
  895. end;
  896. {*****************************************************************************
  897. Emit Functions
  898. *****************************************************************************}
  899. procedure push_shortstring_length(p:tnode);
  900. var
  901. hightree : tnode;
  902. srsym : tsym;
  903. begin
  904. if is_open_string(p.resulttype.def) then
  905. begin
  906. srsym:=searchsymonlyin(tloadnode(p).symtable,'high'+tvarsym(tloadnode(p).symtableentry).name);
  907. hightree:=cloadnode.create(tvarsym(srsym),tloadnode(p).symtable);
  908. firstpass(hightree);
  909. secondpass(hightree);
  910. push_value_para(hightree,false,false,0,4);
  911. hightree.free;
  912. hightree:=nil;
  913. end
  914. else
  915. begin
  916. push_int(tstringdef(p.resulttype.def).len);
  917. end;
  918. end;
  919. {*****************************************************************************
  920. String functions
  921. *****************************************************************************}
  922. procedure loadshortstring(source,dest : tnode);
  923. {
  924. Load a string, handles stringdef and orddef (char) types
  925. }
  926. var
  927. href: treference;
  928. begin
  929. case source.resulttype.def.deftype of
  930. stringdef:
  931. begin
  932. if (source.nodetype=stringconstn) and
  933. (str_length(source)=0) then
  934. emit_const_ref(
  935. A_MOV,S_B,0,newreference(dest.location.reference))
  936. else
  937. begin
  938. emitpushreferenceaddr(dest.location.reference);
  939. emitpushreferenceaddr(source.location.reference);
  940. push_shortstring_length(dest);
  941. emitcall('FPC_SHORTSTR_COPY');
  942. maybe_loadself;
  943. end;
  944. end;
  945. orddef:
  946. begin
  947. if source.nodetype=ordconstn then
  948. emit_const_ref(
  949. A_MOV,S_W,tordconstnode(source).value*256+1,newreference(dest.location.reference))
  950. else
  951. begin
  952. if (source.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  953. begin
  954. href := dest.location.reference;
  955. emit_const_ref(A_MOV,S_B,1,newreference(href));
  956. inc(href.offset,1);
  957. emit_reg_ref(A_MOV,S_B,makereg8(source.location.register),
  958. newreference(href));
  959. ungetregister(source.location.register);
  960. end
  961. else
  962. { not so elegant (goes better with extra register }
  963. begin
  964. { not "movl", because then we may read past the }
  965. { end of the heap! "movw" would be ok too, but }
  966. { I don't think that would be faster (JM) }
  967. getexplicitregister32(R_EDI);
  968. emit_ref_reg(A_MOVZX,S_BL,newreference(source.location.reference),R_EDI);
  969. del_reference(source.location.reference);
  970. emit_const_reg(A_SHL,S_L,8,R_EDI);
  971. emit_const_reg(A_OR,S_L,1,R_EDI);
  972. emit_reg_ref(A_MOV,S_W,R_DI,newreference(dest.location.reference));
  973. ungetregister32(R_EDI);
  974. end;
  975. end;
  976. end;
  977. else
  978. CGMessage(type_e_mismatch);
  979. end;
  980. end;
  981. procedure loadlongstring(p:tbinarynode);
  982. {
  983. Load a string, handles stringdef and orddef (char) types
  984. }
  985. var
  986. r : preference;
  987. begin
  988. case p.right.resulttype.def.deftype of
  989. stringdef:
  990. begin
  991. if (p.right.nodetype=stringconstn) and
  992. (str_length(p.right)=0) then
  993. emit_const_ref(A_MOV,S_L,0,newreference(p.left.location.reference))
  994. else
  995. begin
  996. emitpushreferenceaddr(p.left.location.reference);
  997. emitpushreferenceaddr(p.right.location.reference);
  998. push_shortstring_length(p.left);
  999. emitcall('FPC_LONGSTR_COPY');
  1000. maybe_loadself;
  1001. end;
  1002. end;
  1003. orddef:
  1004. begin
  1005. emit_const_ref(A_MOV,S_L,1,newreference(p.left.location.reference));
  1006. r:=newreference(p.left.location.reference);
  1007. inc(r^.offset,4);
  1008. if p.right.nodetype=ordconstn then
  1009. emit_const_ref(A_MOV,S_B,tordconstnode(p.right).value,r)
  1010. else
  1011. begin
  1012. case p.right.location.loc of
  1013. LOC_REGISTER,LOC_CREGISTER:
  1014. begin
  1015. emit_reg_ref(A_MOV,S_B,p.right.location.register,r);
  1016. ungetregister(p.right.location.register);
  1017. end;
  1018. LOC_MEM,LOC_REFERENCE:
  1019. begin
  1020. if not(R_EAX in unused) then
  1021. emit_reg(A_PUSH,S_L,R_EAX);
  1022. emit_ref_reg(A_MOV,S_B,newreference(p.right.location.reference),R_AL);
  1023. emit_reg_ref(A_MOV,S_B,R_AL,r);
  1024. if not(R_EAX in unused) then
  1025. emit_reg(A_POP,S_L,R_EAX);
  1026. del_reference(p.right.location.reference);
  1027. end
  1028. else
  1029. internalerror(20799);
  1030. end;
  1031. end;
  1032. end;
  1033. else
  1034. CGMessage(type_e_mismatch);
  1035. end;
  1036. end;
  1037. procedure loadansi2short(source,dest : tnode);
  1038. var
  1039. pushed : tpushed;
  1040. regs_to_push: byte;
  1041. begin
  1042. { Find out which registers have to be pushed (JM) }
  1043. regs_to_push := $ff;
  1044. remove_non_regvars_from_loc(source.location,regs_to_push);
  1045. { Push them (JM) }
  1046. pushusedregisters(pushed,regs_to_push);
  1047. case source.location.loc of
  1048. LOC_REFERENCE,LOC_MEM:
  1049. begin
  1050. { Now release the location and registers (see cgai386.pas: }
  1051. { loadansistring for more info on the order) (JM) }
  1052. ungetiftemp(source.location.reference);
  1053. del_reference(source.location.reference);
  1054. emit_push_mem(source.location.reference);
  1055. end;
  1056. LOC_REGISTER,LOC_CREGISTER:
  1057. begin
  1058. emit_reg(A_PUSH,S_L,source.location.register);
  1059. { Now release the register (JM) }
  1060. ungetregister32(source.location.register);
  1061. end;
  1062. end;
  1063. push_shortstring_length(dest);
  1064. emitpushreferenceaddr(dest.location.reference);
  1065. saveregvars($ff);
  1066. emitcall('FPC_ANSISTR_TO_SHORTSTR');
  1067. popusedregisters(pushed);
  1068. maybe_loadself;
  1069. end;
  1070. procedure loadwide2short(source,dest : tnode);
  1071. var
  1072. pushed : tpushed;
  1073. regs_to_push: byte;
  1074. begin
  1075. { Find out which registers have to be pushed (JM) }
  1076. regs_to_push := $ff;
  1077. remove_non_regvars_from_loc(source.location,regs_to_push);
  1078. { Push them (JM) }
  1079. pushusedregisters(pushed,regs_to_push);
  1080. case source.location.loc of
  1081. LOC_REFERENCE,LOC_MEM:
  1082. begin
  1083. { Now release the location and registers (see cgai386.pas: }
  1084. { loadansistring for more info on the order) (JM) }
  1085. ungetiftemp(source.location.reference);
  1086. del_reference(source.location.reference);
  1087. emit_push_mem(source.location.reference);
  1088. end;
  1089. LOC_REGISTER,LOC_CREGISTER:
  1090. begin
  1091. emit_reg(A_PUSH,S_L,source.location.register);
  1092. { Now release the register (JM) }
  1093. ungetregister32(source.location.register);
  1094. end;
  1095. end;
  1096. push_shortstring_length(dest);
  1097. emitpushreferenceaddr(dest.location.reference);
  1098. saveregvars($ff);
  1099. emitcall('FPC_WIDESTR_TO_SHORTSTR');
  1100. popusedregisters(pushed);
  1101. maybe_loadself;
  1102. end;
  1103. procedure loadinterfacecom(p: tbinarynode);
  1104. {
  1105. copies an com interface from n.right to n.left, we
  1106. assume, that both sides are com interface, firstassignement have
  1107. to take care of that, an com interface can't be a register variable
  1108. }
  1109. var
  1110. pushed : tpushed;
  1111. ungettemp : boolean;
  1112. begin
  1113. { before pushing any parameter, we have to save all used }
  1114. { registers, but before that we have to release the }
  1115. { registers of that node to save uneccessary pushed }
  1116. { so be careful, if you think you can optimize that code (FK) }
  1117. { nevertheless, this has to be changed, because otherwise the }
  1118. { register is released before it's contents are pushed -> }
  1119. { problems with the optimizer (JM) }
  1120. del_reference(p.left.location.reference);
  1121. ungettemp:=false;
  1122. case p.right.location.loc of
  1123. LOC_REGISTER,LOC_CREGISTER:
  1124. begin
  1125. pushusedregisters(pushed, $ff xor ($80 shr byte(p.right.location.register)));
  1126. exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.right.location.register));
  1127. ungetregister32(p.right.location.register);
  1128. end;
  1129. LOC_REFERENCE,LOC_MEM:
  1130. begin
  1131. pushusedregisters(pushed,$ff
  1132. xor ($80 shr byte(p.right.location.reference.base))
  1133. xor ($80 shr byte(p.right.location.reference.index)));
  1134. emit_push_mem(p.right.location.reference);
  1135. del_reference(p.right.location.reference);
  1136. ungettemp:=true;
  1137. end;
  1138. end;
  1139. emitpushreferenceaddr(p.left.location.reference);
  1140. del_reference(p.left.location.reference);
  1141. saveregvars($ff);
  1142. emitcall('FPC_INTF_ASSIGN');
  1143. maybe_loadself;
  1144. popusedregisters(pushed);
  1145. if ungettemp then
  1146. ungetiftemp(p.right.location.reference);
  1147. end;
  1148. end.
  1149. {
  1150. $Log$
  1151. Revision 1.25 2001-12-30 17:24:47 jonas
  1152. * range checking is now processor independent (part in cgobj, part in cg64f32) and should work correctly again (it needed some changes after the changes of the low and high of tordef's to int64) * maketojumpbool() is now processor independent (in ncgutil) * getregister32 is now called getregisterint
  1153. Revision 1.24 2001/12/03 21:48:43 peter
  1154. * freemem change to value parameter
  1155. * torddef low/high range changed to int64
  1156. Revision 1.23 2001/12/02 16:19:17 jonas
  1157. * less unnecessary regvar loading with if-statements
  1158. Revision 1.22 2001/10/12 13:51:52 jonas
  1159. * fixed internalerror(10) due to previous fpu overflow fixes ("merged")
  1160. * fixed bug in n386add (introduced after compilerproc changes for string
  1161. operations) where calcregisters wasn't called for shortstring addnodes
  1162. * NOTE: from now on, the location of a binary node must now always be set
  1163. before you call calcregisters() for it
  1164. Revision 1.21 2001/09/17 21:29:14 peter
  1165. * merged netbsd, fpu-overflow from fixes branch
  1166. Revision 1.20 2001/08/26 13:37:01 florian
  1167. * some cg reorganisation
  1168. * some PPC updates
  1169. Revision 1.19 2001/08/24 12:22:14 jonas
  1170. * fixed memory leak with coping of array-of-consts as valuepara
  1171. Revision 1.18 2001/07/08 21:00:18 peter
  1172. * various widestring updates, it works now mostly without charset
  1173. mapping supported
  1174. Revision 1.17 2001/07/01 20:16:20 peter
  1175. * alignmentinfo record added
  1176. * -Oa argument supports more alignment settings that can be specified
  1177. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  1178. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  1179. required alignment and the maximum usefull alignment. The final
  1180. alignment will be choosen per variable size dependent on these
  1181. settings
  1182. Revision 1.16 2001/04/18 22:02:03 peter
  1183. * registration of targets and assemblers
  1184. Revision 1.15 2001/04/13 01:22:19 peter
  1185. * symtable change to classes
  1186. * range check generation and errors fixed, make cycle DEBUG=1 works
  1187. * memory leaks fixed
  1188. Revision 1.14 2001/04/02 21:20:39 peter
  1189. * resulttype rewrite
  1190. Revision 1.13 2001/03/11 22:58:52 peter
  1191. * getsym redesign, removed the globals srsym,srsymtable
  1192. Revision 1.12 2001/03/04 10:26:56 jonas
  1193. * new rangecheck code now handles conversion between signed and cardinal types correctly
  1194. Revision 1.11 2001/03/03 12:41:22 jonas
  1195. * simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
  1196. Revision 1.10 2000/12/31 11:02:12 jonas
  1197. * optimized loadshortstring a bit
  1198. Revision 1.9 2000/12/25 00:07:33 peter
  1199. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1200. tlinkedlist objects)
  1201. Revision 1.8 2000/12/11 19:10:19 jonas
  1202. * fixed web bug 1144
  1203. + implemented range checking for 64bit types
  1204. Revision 1.7 2000/12/07 17:19:46 jonas
  1205. * new constant handling: from now on, hex constants >$7fffffff are
  1206. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1207. and became $ffffffff80000000), all constants in the longint range
  1208. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1209. are cardinals and the rest are int64's.
  1210. * added lots of longint typecast to prevent range check errors in the
  1211. compiler and rtl
  1212. * type casts of symbolic ordinal constants are now preserved
  1213. * fixed bug where the original resulttype.def wasn't restored correctly
  1214. after doing a 64bit rangecheck
  1215. Revision 1.6 2000/12/05 11:44:34 jonas
  1216. + new integer regvar handling, should be much more efficient
  1217. Revision 1.5 2000/11/29 00:30:49 florian
  1218. * unused units removed from uses clause
  1219. * some changes for widestrings
  1220. Revision 1.4 2000/11/13 14:47:46 jonas
  1221. * support for range checking when converting from 64bit to something
  1222. smaller (32bit, 16bit, 8bit)
  1223. * fixed range checking between longint/cardinal and for array indexing
  1224. with cardinal (values > $7fffffff were considered negative)
  1225. Revision 1.3 2000/11/04 14:25:25 florian
  1226. + merged Attila's changes for interfaces, not tested yet
  1227. Revision 1.2 2000/10/31 22:02:57 peter
  1228. * symtable splitted, no real code changes
  1229. Revision 1.1 2000/10/15 09:33:32 peter
  1230. * moved n386*.pas to i386/ cpu_target dir
  1231. Revision 1.3 2000/10/14 21:52:54 peter
  1232. * fixed memory leaks
  1233. Revision 1.2 2000/10/14 10:14:50 peter
  1234. * moehrendorf oct 2000 rewrite
  1235. Revision 1.1 2000/10/01 19:58:40 peter
  1236. * new file
  1237. }