2
0

n386util.pas 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  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. symtable,node;
  23. function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
  24. {$ifdef TEMPS_NOT_PUSH}
  25. function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
  26. {$endif TEMPS_NOT_PUSH}
  27. procedure restore(p : tnode;isint64 : boolean);
  28. {$ifdef TEMPS_NOT_PUSH}
  29. procedure restorefromtemp(p : tnode;isint64 : boolean);
  30. {$endif TEMPS_NOT_PUSH}
  31. procedure pushsetelement(p : tnode);
  32. procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
  33. para_offset:longint;alignment : longint);
  34. procedure loadshortstring(source,dest : tnode);
  35. procedure loadlongstring(p:tbinarynode);
  36. procedure loadansi2short(source,dest : tnode);
  37. procedure maketojumpbool(p : tnode);
  38. procedure emitoverflowcheck(p:tnode);
  39. procedure emitrangecheck(p:tnode;todef:pdef);
  40. procedure firstcomplex(p : tbinarynode);
  41. implementation
  42. uses
  43. globtype,globals,systems,verbose,
  44. cutils,cobjects,
  45. aasm,cpubase,cpuasm,
  46. symconst,
  47. {$ifdef GDB}
  48. gdb,
  49. {$endif GDB}
  50. types,
  51. ncon,nld,
  52. pass_1,pass_2,
  53. hcodegen,tgeni386,temp_gen,
  54. cgai386;
  55. {*****************************************************************************
  56. Emit Push Functions
  57. *****************************************************************************}
  58. function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
  59. var
  60. pushed : boolean;
  61. {hregister : tregister; }
  62. {$ifdef TEMPS_NOT_PUSH}
  63. href : treference;
  64. {$endif TEMPS_NOT_PUSH}
  65. begin
  66. if needed>usablereg32 then
  67. begin
  68. if (p.location.loc=LOC_REGISTER) then
  69. begin
  70. if isint64 then
  71. begin
  72. {$ifdef TEMPS_NOT_PUSH}
  73. gettempofsizereference(href,8);
  74. p.temp_offset:=href.offset;
  75. href.offset:=href.offset+4;
  76. exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p.location.registerhigh,href)));
  77. href.offset:=href.offset-4;
  78. {$else TEMPS_NOT_PUSH}
  79. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerhigh)));
  80. {$endif TEMPS_NOT_PUSH}
  81. ungetregister32(p.location.registerhigh);
  82. end
  83. {$ifdef TEMPS_NOT_PUSH}
  84. else
  85. begin
  86. gettempofsizereference(href,4);
  87. p.temp_offset:=href.offset;
  88. end
  89. {$endif TEMPS_NOT_PUSH}
  90. ;
  91. pushed:=true;
  92. {$ifdef TEMPS_NOT_PUSH}
  93. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p.location.register,href)));
  94. {$else TEMPS_NOT_PUSH}
  95. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.register)));
  96. {$endif TEMPS_NOT_PUSH}
  97. ungetregister32(p.location.register);
  98. end
  99. else if (p.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  100. ((p.location.reference.base<>R_NO) or
  101. (p.location.reference.index<>R_NO)
  102. ) then
  103. begin
  104. del_reference(p.location.reference);
  105. getexplicitregister32(R_EDI);
  106. emit_ref_reg(A_LEA,S_L,newreference(p.location.reference),R_EDI);
  107. {$ifdef TEMPS_NOT_PUSH}
  108. gettempofsizereference(href,4);
  109. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
  110. p.temp_offset:=href.offset;
  111. {$else TEMPS_NOT_PUSH}
  112. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  113. {$endif TEMPS_NOT_PUSH}
  114. ungetregister32(R_EDI);
  115. pushed:=true;
  116. end
  117. else pushed:=false;
  118. end
  119. else pushed:=false;
  120. maybe_push:=pushed;
  121. end;
  122. {$ifdef TEMPS_NOT_PUSH}
  123. function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
  124. var
  125. pushed : boolean;
  126. href : treference;
  127. begin
  128. if needed>usablereg32 then
  129. begin
  130. if (p^.location.loc=LOC_REGISTER) then
  131. begin
  132. if isint64(p^.resulttype) then
  133. begin
  134. gettempofsizereference(href,8);
  135. p^.temp_offset:=href.offset;
  136. href.offset:=href.offset+4;
  137. exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p^.location.registerhigh,href)));
  138. href.offset:=href.offset-4;
  139. ungetregister32(p^.location.registerhigh);
  140. end
  141. else
  142. begin
  143. gettempofsizereference(href,4);
  144. p^.temp_offset:=href.offset;
  145. end;
  146. pushed:=true;
  147. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p^.location.register,href)));
  148. ungetregister32(p^.location.register);
  149. end
  150. else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  151. ((p^.location.reference.base<>R_NO) or
  152. (p^.location.reference.index<>R_NO)
  153. ) then
  154. begin
  155. del_reference(p^.location.reference);
  156. getexplicitregister32(R_EDI);
  157. emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
  158. R_EDI);
  159. gettempofsizereference(href,4);
  160. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
  161. ungetregister32(R_EDI);
  162. p^.temp_offset:=href.offset;
  163. pushed:=true;
  164. end
  165. else pushed:=false;
  166. end
  167. else pushed:=false;
  168. maybe_push:=pushed;
  169. end;
  170. {$endif TEMPS_NOT_PUSH}
  171. procedure restore(p : tnode;isint64 : boolean);
  172. var
  173. hregister : tregister;
  174. {$ifdef TEMPS_NOT_PUSH}
  175. href : treference;
  176. {$endif TEMPS_NOT_PUSH}
  177. begin
  178. hregister:=getregister32;
  179. {$ifdef TEMPS_NOT_PUSH}
  180. reset_reference(href);
  181. href.base:=procinfo^.frame_pointer;
  182. href.offset:=p.temp_offset;
  183. emit_ref_reg(A_MOV,S_L,href,hregister);
  184. {$else TEMPS_NOT_PUSH}
  185. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,hregister)));
  186. {$endif TEMPS_NOT_PUSH}
  187. if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  188. begin
  189. p.location.register:=hregister;
  190. if isint64 then
  191. begin
  192. p.location.registerhigh:=getregister32;
  193. {$ifdef TEMPS_NOT_PUSH}
  194. href.offset:=p.temp_offset+4;
  195. emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
  196. { set correctly for release ! }
  197. href.offset:=p.temp_offset;
  198. {$else TEMPS_NOT_PUSH}
  199. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,p.location.registerhigh)));
  200. {$endif TEMPS_NOT_PUSH}
  201. end;
  202. end
  203. else
  204. begin
  205. reset_reference(p.location.reference);
  206. { any reasons why this was moved into the index register ? }
  207. { normally usage of base register is much better (FK) }
  208. p.location.reference.base:=hregister;
  209. { Why is this done? We can never be sure about p.left
  210. because otherwise secondload fails !!!
  211. set_location(p.left^.location,p.location);}
  212. end;
  213. {$ifdef TEMPS_NOT_PUSH}
  214. ungetiftemp(href);
  215. {$endif TEMPS_NOT_PUSH}
  216. end;
  217. {$ifdef TEMPS_NOT_PUSH}
  218. procedure restorefromtemp(p : tnode;isint64 : boolean);
  219. var
  220. hregister : tregister;
  221. href : treference;
  222. begin
  223. hregister:=getregister32;
  224. reset_reference(href);
  225. href.base:=procinfo^.frame_pointer;
  226. href.offset:=p.temp_offset;
  227. emit_ref_reg(A_MOV,S_L,href,hregister);
  228. if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  229. begin
  230. p.location.register:=hregister;
  231. if isint64 then
  232. begin
  233. p.location.registerhigh:=getregister32;
  234. href.offset:=p.temp_offset+4;
  235. emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
  236. { set correctly for release ! }
  237. href.offset:=p.temp_offset;
  238. end;
  239. end
  240. else
  241. begin
  242. reset_reference(p.location.reference);
  243. p.location.reference.base:=hregister;
  244. { Why is this done? We can never be sure about p^.left
  245. because otherwise secondload fails PM
  246. set_location(p^.left^.location,p^.location);}
  247. end;
  248. ungetiftemp(href);
  249. end;
  250. {$endif TEMPS_NOT_PUSH}
  251. procedure pushsetelement(p : tnode);
  252. var
  253. hr,hr16,hr32 : tregister;
  254. begin
  255. { copy the element on the stack, slightly complicated }
  256. if p.nodetype=ordconstn then
  257. begin
  258. if target_os.stackalignment=4 then
  259. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,tordconstnode(p).value)))
  260. else
  261. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_W,tordconstnode(p).value)));
  262. end
  263. else
  264. begin
  265. case p.location.loc of
  266. LOC_REGISTER,
  267. LOC_CREGISTER :
  268. begin
  269. hr:=p.location.register;
  270. case hr of
  271. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  272. begin
  273. hr16:=reg32toreg16(hr);
  274. hr32:=hr;
  275. end;
  276. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  277. begin
  278. hr16:=hr;
  279. hr32:=reg16toreg32(hr);
  280. end;
  281. R_AL,R_BL,R_CL,R_DL :
  282. begin
  283. hr16:=reg8toreg16(hr);
  284. hr32:=reg8toreg32(hr);
  285. end;
  286. end;
  287. if target_os.stackalignment=4 then
  288. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,hr32)))
  289. else
  290. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,hr16)));
  291. ungetregister32(hr32);
  292. end;
  293. else
  294. begin
  295. { you can't push more bytes than the size of the element, }
  296. { because this may cross a page boundary and you'll get a }
  297. { sigsegv (JM) }
  298. emit_push_mem_size(p.location.reference,1);
  299. del_reference(p.location.reference);
  300. end;
  301. end;
  302. end;
  303. end;
  304. procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
  305. para_offset:longint;alignment : longint);
  306. var
  307. tempreference : treference;
  308. r : preference;
  309. opsize : topsize;
  310. op : tasmop;
  311. hreg : tregister;
  312. size : longint;
  313. hlabel : pasmlabel;
  314. begin
  315. case p.location.loc of
  316. LOC_REGISTER,
  317. LOC_CREGISTER:
  318. begin
  319. case p.location.register of
  320. R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
  321. R_EDI,R_ESP,R_EBP :
  322. begin
  323. if p.resulttype^.size=8 then
  324. begin
  325. inc(pushedparasize,8);
  326. if inlined then
  327. begin
  328. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  329. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  330. p.location.registerlow,r)));
  331. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
  332. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  333. p.location.registerhigh,r)));
  334. end
  335. else
  336. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerhigh)));
  337. ungetregister32(p.location.registerhigh);
  338. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerlow)));
  339. ungetregister32(p.location.registerlow);
  340. end
  341. else
  342. begin
  343. inc(pushedparasize,4);
  344. if inlined then
  345. begin
  346. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  347. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  348. p.location.register,r)));
  349. end
  350. else
  351. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.register)));
  352. ungetregister32(p.location.register);
  353. end;
  354. end;
  355. R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
  356. begin
  357. if alignment=4 then
  358. begin
  359. opsize:=S_L;
  360. hreg:=reg16toreg32(p.location.register);
  361. inc(pushedparasize,4);
  362. end
  363. else
  364. begin
  365. opsize:=S_W;
  366. hreg:=p.location.register;
  367. inc(pushedparasize,2);
  368. end;
  369. if inlined then
  370. begin
  371. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  372. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  373. end
  374. else
  375. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
  376. ungetregister32(reg16toreg32(p.location.register));
  377. end;
  378. R_AL,R_BL,R_CL,R_DL:
  379. begin
  380. if alignment=4 then
  381. begin
  382. opsize:=S_L;
  383. hreg:=reg8toreg32(p.location.register);
  384. inc(pushedparasize,4);
  385. end
  386. else
  387. begin
  388. opsize:=S_W;
  389. hreg:=reg8toreg16(p.location.register);
  390. inc(pushedparasize,2);
  391. end;
  392. { we must push always 16 bit }
  393. if inlined then
  394. begin
  395. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  396. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  397. end
  398. else
  399. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
  400. ungetregister32(reg8toreg32(p.location.register));
  401. end;
  402. else internalerror(1899);
  403. end;
  404. end;
  405. LOC_FPU:
  406. begin
  407. size:=align(pfloatdef(p.resulttype)^.size,alignment);
  408. inc(pushedparasize,size);
  409. if not inlined then
  410. emit_const_reg(A_SUB,S_L,size,R_ESP);
  411. {$ifdef GDB}
  412. if (cs_debuginfo in aktmoduleswitches) and
  413. (exprasmlist^.first=exprasmlist^.last) then
  414. exprasmlist^.concat(new(pai_force_line,init));
  415. {$endif GDB}
  416. r:=new_reference(R_ESP,0);
  417. floatstoreops(pfloatdef(p.resulttype)^.typ,op,opsize);
  418. { this is the easiest case for inlined !! }
  419. if inlined then
  420. begin
  421. r^.base:=procinfo^.framepointer;
  422. r^.offset:=para_offset-pushedparasize;
  423. end;
  424. exprasmlist^.concat(new(paicpu,op_ref(op,opsize,r)));
  425. dec(fpuvaroffset);
  426. end;
  427. LOC_CFPUREGISTER:
  428. begin
  429. exprasmlist^.concat(new(paicpu,op_reg(A_FLD,S_NO,
  430. correct_fpuregister(p.location.register,fpuvaroffset))));
  431. size:=align(pfloatdef(p.resulttype)^.size,alignment);
  432. inc(pushedparasize,size);
  433. if not inlined then
  434. emit_const_reg(A_SUB,S_L,size,R_ESP);
  435. {$ifdef GDB}
  436. if (cs_debuginfo in aktmoduleswitches) and
  437. (exprasmlist^.first=exprasmlist^.last) then
  438. exprasmlist^.concat(new(pai_force_line,init));
  439. {$endif GDB}
  440. r:=new_reference(R_ESP,0);
  441. floatstoreops(pfloatdef(p.resulttype)^.typ,op,opsize);
  442. { this is the easiest case for inlined !! }
  443. if inlined then
  444. begin
  445. r^.base:=procinfo^.framepointer;
  446. r^.offset:=para_offset-pushedparasize;
  447. end;
  448. exprasmlist^.concat(new(paicpu,op_ref(op,opsize,r)));
  449. end;
  450. LOC_REFERENCE,LOC_MEM:
  451. begin
  452. tempreference:=p.location.reference;
  453. del_reference(p.location.reference);
  454. case p.resulttype^.deftype of
  455. enumdef,
  456. orddef :
  457. begin
  458. case p.resulttype^.size of
  459. 8 : begin
  460. inc(pushedparasize,8);
  461. if inlined then
  462. begin
  463. getexplicitregister32(R_EDI);
  464. emit_ref_reg(A_MOV,S_L,
  465. newreference(tempreference),R_EDI);
  466. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  467. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  468. ungetregister32(R_EDI);
  469. getexplicitregister32(R_EDI);
  470. inc(tempreference.offset,4);
  471. emit_ref_reg(A_MOV,S_L,
  472. newreference(tempreference),R_EDI);
  473. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
  474. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  475. ungetregister32(R_EDI);
  476. end
  477. else
  478. begin
  479. inc(tempreference.offset,4);
  480. emit_push_mem(tempreference);
  481. dec(tempreference.offset,4);
  482. emit_push_mem(tempreference);
  483. end;
  484. end;
  485. 4 : begin
  486. inc(pushedparasize,4);
  487. if inlined then
  488. begin
  489. getexplicitregister32(R_EDI);
  490. emit_ref_reg(A_MOV,S_L,
  491. newreference(tempreference),R_EDI);
  492. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  493. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  494. ungetregister32(R_EDI);
  495. end
  496. else
  497. emit_push_mem(tempreference);
  498. end;
  499. 1,2 : begin
  500. if alignment=4 then
  501. begin
  502. opsize:=S_L;
  503. hreg:=R_EDI;
  504. inc(pushedparasize,4);
  505. end
  506. else
  507. begin
  508. opsize:=S_W;
  509. hreg:=R_DI;
  510. inc(pushedparasize,2);
  511. end;
  512. if inlined then
  513. begin
  514. getexplicitregister32(R_EDI);
  515. emit_ref_reg(A_MOV,opsize,
  516. newreference(tempreference),hreg);
  517. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  518. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  519. ungetregister32(R_EDI);
  520. end
  521. else
  522. emit_push_mem_size(tempreference,p.resulttype^.size);
  523. end;
  524. else
  525. internalerror(234231);
  526. end;
  527. end;
  528. floatdef :
  529. begin
  530. case pfloatdef(p.resulttype)^.typ of
  531. f32bit,
  532. s32real :
  533. begin
  534. inc(pushedparasize,4);
  535. if inlined then
  536. begin
  537. getexplicitregister32(R_EDI);
  538. emit_ref_reg(A_MOV,S_L,
  539. newreference(tempreference),R_EDI);
  540. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  541. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  542. ungetregister32(R_EDI);
  543. end
  544. else
  545. emit_push_mem(tempreference);
  546. end;
  547. s64real,
  548. s64comp :
  549. begin
  550. inc(pushedparasize,4);
  551. inc(tempreference.offset,4);
  552. if inlined then
  553. begin
  554. getexplicitregister32(R_EDI);
  555. emit_ref_reg(A_MOV,S_L,
  556. newreference(tempreference),R_EDI);
  557. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  558. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  559. ungetregister32(R_EDI);
  560. end
  561. else
  562. emit_push_mem(tempreference);
  563. inc(pushedparasize,4);
  564. dec(tempreference.offset,4);
  565. if inlined then
  566. begin
  567. getexplicitregister32(R_EDI);
  568. emit_ref_reg(A_MOV,S_L,
  569. newreference(tempreference),R_EDI);
  570. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  571. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  572. ungetregister32(R_EDI);
  573. end
  574. else
  575. emit_push_mem(tempreference);
  576. end;
  577. s80real :
  578. begin
  579. inc(pushedparasize,4);
  580. if alignment=4 then
  581. inc(tempreference.offset,8)
  582. else
  583. inc(tempreference.offset,6);
  584. if inlined then
  585. begin
  586. getexplicitregister32(R_EDI);
  587. emit_ref_reg(A_MOV,S_L,
  588. newreference(tempreference),R_EDI);
  589. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  590. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  591. ungetregister32(R_EDI);
  592. end
  593. else
  594. emit_push_mem(tempreference);
  595. dec(tempreference.offset,4);
  596. inc(pushedparasize,4);
  597. if inlined then
  598. begin
  599. getexplicitregister32(R_EDI);
  600. emit_ref_reg(A_MOV,S_L,
  601. newreference(tempreference),R_EDI);
  602. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  603. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  604. ungetregister32(R_EDI);
  605. end
  606. else
  607. emit_push_mem(tempreference);
  608. if alignment=4 then
  609. begin
  610. opsize:=S_L;
  611. hreg:=R_EDI;
  612. inc(pushedparasize,4);
  613. dec(tempreference.offset,4);
  614. end
  615. else
  616. begin
  617. opsize:=S_W;
  618. hreg:=R_DI;
  619. inc(pushedparasize,2);
  620. dec(tempreference.offset,2);
  621. end;
  622. if inlined then
  623. begin
  624. getexplicitregister32(R_EDI);
  625. emit_ref_reg(A_MOV,opsize,
  626. newreference(tempreference),hreg);
  627. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  628. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  629. ungetregister32(R_EDI);
  630. end
  631. else
  632. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,opsize,
  633. newreference(tempreference))));
  634. end;
  635. end;
  636. end;
  637. pointerdef,
  638. procvardef,
  639. classrefdef:
  640. begin
  641. inc(pushedparasize,4);
  642. if inlined then
  643. begin
  644. getexplicitregister32(R_EDI);
  645. emit_ref_reg(A_MOV,S_L,
  646. newreference(tempreference),R_EDI);
  647. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  648. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  649. ungetregister32(R_EDI);
  650. end
  651. else
  652. emit_push_mem(tempreference);
  653. end;
  654. arraydef,
  655. recorddef,
  656. stringdef,
  657. setdef,
  658. objectdef :
  659. begin
  660. { even some structured types are 32 bit }
  661. if is_widestring(p.resulttype) or
  662. is_ansistring(p.resulttype) or
  663. is_smallset(p.resulttype) or
  664. ((p.resulttype^.deftype in [recorddef,arraydef]) and
  665. (
  666. (p.resulttype^.deftype<>arraydef) or not
  667. (parraydef(p.resulttype)^.IsConstructor or
  668. parraydef(p.resulttype)^.isArrayOfConst or
  669. is_open_array(p.resulttype))
  670. ) and
  671. (p.resulttype^.size<=4)
  672. ) or
  673. ((p.resulttype^.deftype=objectdef) and
  674. pobjectdef(p.resulttype)^.is_class) then
  675. begin
  676. if (p.resulttype^.size>2) or
  677. ((alignment=4) and (p.resulttype^.size>0)) then
  678. begin
  679. inc(pushedparasize,4);
  680. if inlined then
  681. begin
  682. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  683. concatcopy(tempreference,r^,4,false,false);
  684. end
  685. else
  686. emit_push_mem(tempreference);
  687. end
  688. else
  689. begin
  690. if p.resulttype^.size>0 then
  691. begin
  692. inc(pushedparasize,2);
  693. if inlined then
  694. begin
  695. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  696. concatcopy(tempreference,r^,2,false,false);
  697. end
  698. else
  699. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_W,newreference(tempreference))));
  700. end;
  701. end;
  702. end
  703. { call by value open array ? }
  704. else if is_cdecl then
  705. begin
  706. { push on stack }
  707. size:=align(p.resulttype^.size,alignment);
  708. inc(pushedparasize,size);
  709. emit_const_reg(A_SUB,S_L,size,R_ESP);
  710. r:=new_reference(R_ESP,0);
  711. concatcopy(tempreference,r^,size,false,false);
  712. end
  713. else
  714. internalerror(8954);
  715. end;
  716. else
  717. CGMessage(cg_e_illegal_expression);
  718. end;
  719. end;
  720. LOC_JUMP:
  721. begin
  722. getlabel(hlabel);
  723. if alignment=4 then
  724. begin
  725. opsize:=S_L;
  726. inc(pushedparasize,4);
  727. end
  728. else
  729. begin
  730. opsize:=S_W;
  731. inc(pushedparasize,2);
  732. end;
  733. emitlab(truelabel);
  734. if inlined then
  735. begin
  736. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  737. emit_const_ref(A_MOV,opsize,1,r);
  738. end
  739. else
  740. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,1)));
  741. emitjmp(C_None,hlabel);
  742. emitlab(falselabel);
  743. if inlined then
  744. begin
  745. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  746. emit_const_ref(A_MOV,opsize,0,r);
  747. end
  748. else
  749. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,0)));
  750. emitlab(hlabel);
  751. end;
  752. LOC_FLAGS:
  753. begin
  754. if not(R_EAX in unused) then
  755. begin
  756. getexplicitregister32(R_EDI);
  757. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  758. end;
  759. emit_flag2reg(p.location.resflags,R_AL);
  760. emit_reg_reg(A_MOVZX,S_BW,R_AL,R_AX);
  761. if alignment=4 then
  762. begin
  763. opsize:=S_L;
  764. hreg:=R_EAX;
  765. inc(pushedparasize,4);
  766. end
  767. else
  768. begin
  769. opsize:=S_W;
  770. hreg:=R_AX;
  771. inc(pushedparasize,2);
  772. end;
  773. if inlined then
  774. begin
  775. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  776. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  777. end
  778. else
  779. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
  780. if not(R_EAX in unused) then
  781. begin
  782. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  783. ungetregister32(R_EDI);
  784. end;
  785. end;
  786. {$ifdef SUPPORT_MMX}
  787. LOC_MMXREGISTER,
  788. LOC_CMMXREGISTER:
  789. begin
  790. inc(pushedparasize,8); { was missing !!! (PM) }
  791. emit_const_reg(
  792. A_SUB,S_L,8,R_ESP);
  793. {$ifdef GDB}
  794. if (cs_debuginfo in aktmoduleswitches) and
  795. (exprasmlist^.first=exprasmlist^.last) then
  796. exprasmlist^.concat(new(pai_force_line,init));
  797. {$endif GDB}
  798. if inlined then
  799. begin
  800. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  801. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOVQ,S_NO,
  802. p.location.register,r)));
  803. end
  804. else
  805. begin
  806. r:=new_reference(R_ESP,0);
  807. exprasmlist^.concat(new(paicpu,op_reg_ref(
  808. A_MOVQ,S_NO,p.location.register,r)));
  809. end;
  810. end;
  811. {$endif SUPPORT_MMX}
  812. end;
  813. end;
  814. {*****************************************************************************
  815. Emit Functions
  816. *****************************************************************************}
  817. procedure maketojumpbool(p : tnode);
  818. {
  819. produces jumps to true respectively false labels using boolean expressions
  820. }
  821. var
  822. opsize : topsize;
  823. storepos : tfileposinfo;
  824. begin
  825. if nf_error in p.flags then
  826. exit;
  827. storepos:=aktfilepos;
  828. aktfilepos:=p.fileinfo;
  829. if is_boolean(p.resulttype) then
  830. begin
  831. if is_constboolnode(p) then
  832. begin
  833. if tordconstnode(p).value<>0 then
  834. emitjmp(C_None,truelabel)
  835. else
  836. emitjmp(C_None,falselabel);
  837. end
  838. else
  839. begin
  840. opsize:=def_opsize(p.resulttype);
  841. case p.location.loc of
  842. LOC_CREGISTER,LOC_REGISTER : begin
  843. emit_reg_reg(A_OR,opsize,p.location.register,
  844. p.location.register);
  845. ungetregister(p.location.register);
  846. emitjmp(C_NZ,truelabel);
  847. emitjmp(C_None,falselabel);
  848. end;
  849. LOC_MEM,LOC_REFERENCE : begin
  850. emit_const_ref(
  851. A_CMP,opsize,0,newreference(p.location.reference));
  852. del_reference(p.location.reference);
  853. emitjmp(C_NZ,truelabel);
  854. emitjmp(C_None,falselabel);
  855. end;
  856. LOC_FLAGS : begin
  857. emitjmp(flag_2_cond[p.location.resflags],truelabel);
  858. emitjmp(C_None,falselabel);
  859. end;
  860. end;
  861. end;
  862. end
  863. else
  864. CGMessage(type_e_mismatch);
  865. aktfilepos:=storepos;
  866. end;
  867. { produces if necessary overflowcode }
  868. procedure emitoverflowcheck(p:tnode);
  869. var
  870. hl : pasmlabel;
  871. begin
  872. if not(cs_check_overflow in aktlocalswitches) then
  873. exit;
  874. getlabel(hl);
  875. if not ((p.resulttype^.deftype=pointerdef) or
  876. ((p.resulttype^.deftype=orddef) and
  877. (porddef(p.resulttype)^.typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  878. bool8bit,bool16bit,bool32bit]))) then
  879. emitjmp(C_NO,hl)
  880. else
  881. emitjmp(C_NB,hl);
  882. emitcall('FPC_OVERFLOW');
  883. emitlab(hl);
  884. end;
  885. { produces range check code, while one of the operands is a 64 bit
  886. integer }
  887. procedure emitrangecheck64(p : tnode;todef : pdef);
  888. begin
  889. CGMessage(cg_w_64bit_range_check_not_supported);
  890. {internalerror(28699);}
  891. end;
  892. { produces if necessary rangecheckcode }
  893. procedure emitrangecheck(p:tnode;todef:pdef);
  894. {
  895. generate range checking code for the value at location t. The
  896. type used is the checked against todefs ranges. fromdef (p.resulttype)
  897. is the original type used at that location, when both defs are
  898. equal the check is also insert (needed for succ,pref,inc,dec)
  899. }
  900. var
  901. neglabel,
  902. poslabel : pasmlabel;
  903. href : treference;
  904. rstr : string;
  905. hreg : tregister;
  906. opsize : topsize;
  907. op : tasmop;
  908. fromdef : pdef;
  909. lto,hto,
  910. lfrom,hfrom : longint;
  911. doublebound,
  912. is_reg,
  913. popecx : boolean;
  914. begin
  915. { range checking on and range checkable value? }
  916. if not(cs_check_range in aktlocalswitches) or
  917. not(todef^.deftype in [orddef,enumdef,arraydef]) then
  918. exit;
  919. { only check when assigning to scalar, subranges are different,
  920. when todef=fromdef then the check is always generated }
  921. fromdef:=p.resulttype;
  922. if is_64bitint(fromdef) or is_64bitint(todef) then
  923. begin
  924. emitrangecheck64(p,todef);
  925. exit;
  926. end;
  927. {we also need lto and hto when checking if we need to use doublebound!
  928. (JM)}
  929. getrange(todef,lto,hto);
  930. if todef<>fromdef then
  931. begin
  932. getrange(p.resulttype,lfrom,hfrom);
  933. { first check for not being u32bit, then if the to is bigger than
  934. from }
  935. if (lto<hto) and (lfrom<hfrom) and
  936. (lto<=lfrom) and (hto>=hfrom) then
  937. exit;
  938. end;
  939. { generate the rangecheck code for the def where we are going to
  940. store the result }
  941. doublebound:=false;
  942. case todef^.deftype of
  943. orddef :
  944. begin
  945. porddef(todef)^.genrangecheck;
  946. rstr:=porddef(todef)^.getrangecheckstring;
  947. doublebound:=(porddef(todef)^.typ=u32bit) and (lto>hto);
  948. end;
  949. enumdef :
  950. begin
  951. penumdef(todef)^.genrangecheck;
  952. rstr:=penumdef(todef)^.getrangecheckstring;
  953. end;
  954. arraydef :
  955. begin
  956. parraydef(todef)^.genrangecheck;
  957. rstr:=parraydef(todef)^.getrangecheckstring;
  958. doublebound:=(lto>hto);
  959. end;
  960. end;
  961. { get op and opsize }
  962. opsize:=def2def_opsize(fromdef,u32bitdef);
  963. if opsize in [S_B,S_W,S_L] then
  964. op:=A_MOV
  965. else
  966. if is_signed(fromdef) then
  967. op:=A_MOVSX
  968. else
  969. op:=A_MOVZX;
  970. is_reg:=(p.location.loc in [LOC_REGISTER,LOC_CREGISTER]);
  971. if is_reg then
  972. hreg:=p.location.register;
  973. if not target_os.use_bound_instruction then
  974. begin
  975. { FPC_BOUNDCHECK needs to be called with
  976. %ecx - value
  977. %edi - pointer to the ranges }
  978. popecx:=false;
  979. if not(is_reg) or
  980. (p.location.register<>R_ECX) then
  981. begin
  982. if not(R_ECX in unused) then
  983. begin
  984. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
  985. popecx:=true;
  986. end
  987. else exprasmlist^.concat(new(pairegalloc,alloc(R_ECX)));
  988. if is_reg then
  989. emit_reg_reg(op,opsize,p.location.register,R_ECX)
  990. else
  991. emit_ref_reg(op,opsize,newreference(p.location.reference),R_ECX);
  992. end;
  993. if doublebound then
  994. begin
  995. getlabel(neglabel);
  996. getlabel(poslabel);
  997. emit_reg_reg(A_OR,S_L,R_ECX,R_ECX);
  998. emitjmp(C_L,neglabel);
  999. end;
  1000. { insert bound instruction only }
  1001. getexplicitregister32(R_EDI);
  1002. exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),0,R_EDI)));
  1003. emitcall('FPC_BOUNDCHECK');
  1004. ungetregister32(R_EDI);
  1005. { u32bit needs 2 checks }
  1006. if doublebound then
  1007. begin
  1008. emitjmp(C_None,poslabel);
  1009. emitlab(neglabel);
  1010. getexplicitregister32(R_EDI);
  1011. exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),8,R_EDI)));
  1012. emitcall('FPC_BOUNDCHECK');
  1013. ungetregister32(R_EDI);
  1014. emitlab(poslabel);
  1015. end;
  1016. if popecx then
  1017. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
  1018. else exprasmlist^.concat(new(pairegalloc,dealloc(R_ECX)));
  1019. end
  1020. else
  1021. begin
  1022. reset_reference(href);
  1023. href.symbol:=newasmsymbol(rstr);
  1024. { load the value in a register }
  1025. if is_reg then
  1026. begin
  1027. { be sure that hreg is a 32 bit reg, if not load it in %edi }
  1028. if p.location.register in [R_EAX..R_EDI] then
  1029. hreg:=p.location.register
  1030. else
  1031. begin
  1032. getexplicitregister32(R_EDI);
  1033. emit_reg_reg(op,opsize,p.location.register,R_EDI);
  1034. hreg:=R_EDI;
  1035. end;
  1036. end
  1037. else
  1038. begin
  1039. getexplicitregister32(R_EDI);
  1040. emit_ref_reg(op,opsize,newreference(p.location.reference),R_EDI);
  1041. hreg:=R_EDI;
  1042. end;
  1043. if doublebound then
  1044. begin
  1045. getlabel(neglabel);
  1046. getlabel(poslabel);
  1047. emit_reg_reg(A_TEST,S_L,hreg,hreg);
  1048. emitjmp(C_L,neglabel);
  1049. end;
  1050. { insert bound instruction only }
  1051. exprasmlist^.concat(new(paicpu,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
  1052. { u32bit needs 2 checks }
  1053. if doublebound then
  1054. begin
  1055. href.offset:=8;
  1056. emitjmp(C_None,poslabel);
  1057. emitlab(neglabel);
  1058. exprasmlist^.concat(new(paicpu,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
  1059. emitlab(poslabel);
  1060. end;
  1061. if hreg = R_EDI then
  1062. ungetregister32(R_EDI);
  1063. end;
  1064. end;
  1065. { DO NOT RELY on the fact that the tnode is not yet swaped
  1066. because of inlining code PM }
  1067. procedure firstcomplex(p : tbinarynode);
  1068. var
  1069. hp : tnode;
  1070. begin
  1071. { always calculate boolean AND and OR from left to right }
  1072. if (p.nodetype in [orn,andn]) and
  1073. (p.left.resulttype^.deftype=orddef) and
  1074. (porddef(p.left.resulttype)^.typ in [bool8bit,bool16bit,bool32bit]) then
  1075. begin
  1076. { p.swaped:=false}
  1077. if nf_swaped in p.flags then
  1078. internalerror(234234);
  1079. end
  1080. else
  1081. if (p.left.registers32<p.right.registers32) and
  1082. { the following check is appropriate, because all }
  1083. { 4 registers are rarely used and it is thereby }
  1084. { achieved that the extra code is being dropped }
  1085. { by exchanging not commutative operators }
  1086. (p.right.registers32<=4) then
  1087. begin
  1088. hp:=p.left;
  1089. p.left:=p.right;
  1090. p.right:=hp;
  1091. if nf_swaped in p.flags then
  1092. exclude(p.flags,nf_swaped)
  1093. else
  1094. include(p.flags,nf_swaped);
  1095. end;
  1096. {else
  1097. p.swaped:=false; do not modify }
  1098. end;
  1099. {*****************************************************************************
  1100. Emit Functions
  1101. *****************************************************************************}
  1102. procedure push_shortstring_length(p:tnode);
  1103. var
  1104. hightree : tnode;
  1105. begin
  1106. if is_open_string(p.resulttype) then
  1107. begin
  1108. getsymonlyin(tloadnode(p).symtable,'high'+pvarsym(tloadnode(p).symtableentry)^.name);
  1109. hightree:=genloadnode(pvarsym(srsym),tloadnode(p).symtable);
  1110. firstpass(hightree);
  1111. secondpass(hightree);
  1112. push_value_para(hightree,false,false,0,4);
  1113. hightree.free;
  1114. hightree:=nil;
  1115. end
  1116. else
  1117. begin
  1118. push_int(pstringdef(p.resulttype)^.len);
  1119. end;
  1120. end;
  1121. {*****************************************************************************
  1122. String functions
  1123. *****************************************************************************}
  1124. procedure loadshortstring(source,dest : tnode);
  1125. {
  1126. Load a string, handles stringdef and orddef (char) types
  1127. }
  1128. begin
  1129. case source.resulttype^.deftype of
  1130. stringdef:
  1131. begin
  1132. if (source.nodetype=stringconstn) and
  1133. (str_length(source)=0) then
  1134. emit_const_ref(
  1135. A_MOV,S_B,0,newreference(dest.location.reference))
  1136. else
  1137. begin
  1138. emitpushreferenceaddr(dest.location.reference);
  1139. emitpushreferenceaddr(source.location.reference);
  1140. push_shortstring_length(dest);
  1141. emitcall('FPC_SHORTSTR_COPY');
  1142. maybe_loadesi;
  1143. end;
  1144. end;
  1145. orddef:
  1146. begin
  1147. if source.nodetype=ordconstn then
  1148. emit_const_ref(
  1149. A_MOV,S_W,tordconstnode(source).value*256+1,newreference(dest.location.reference))
  1150. else
  1151. begin
  1152. { not so elegant (goes better with extra register }
  1153. {$ifndef noAllocEdi}
  1154. getexplicitregister32(R_EDI);
  1155. {$endif noAllocEdi}
  1156. if (source.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  1157. begin
  1158. emit_reg_reg(A_MOV,S_L,makereg32(source.location.register),R_EDI);
  1159. ungetregister(source.location.register);
  1160. end
  1161. else
  1162. begin
  1163. emit_ref_reg(A_MOV,S_L,newreference(source.location.reference),R_EDI);
  1164. del_reference(source.location.reference);
  1165. end;
  1166. emit_const_reg(A_SHL,S_L,8,R_EDI);
  1167. emit_const_reg(A_OR,S_L,1,R_EDI);
  1168. emit_reg_ref(A_MOV,S_W,R_DI,newreference(dest.location.reference));
  1169. {$ifndef noAllocEdi}
  1170. ungetregister32(R_EDI);
  1171. {$endif noAllocEdi}
  1172. end;
  1173. end;
  1174. else
  1175. CGMessage(type_e_mismatch);
  1176. end;
  1177. end;
  1178. procedure loadlongstring(p:tbinarynode);
  1179. {
  1180. Load a string, handles stringdef and orddef (char) types
  1181. }
  1182. var
  1183. r : preference;
  1184. begin
  1185. case p.right.resulttype^.deftype of
  1186. stringdef:
  1187. begin
  1188. if (p.right.nodetype=stringconstn) and
  1189. (str_length(p.right)=0) then
  1190. emit_const_ref(A_MOV,S_L,0,newreference(p.left.location.reference))
  1191. else
  1192. begin
  1193. emitpushreferenceaddr(p.left.location.reference);
  1194. emitpushreferenceaddr(p.right.location.reference);
  1195. push_shortstring_length(p.left);
  1196. emitcall('FPC_LONGSTR_COPY');
  1197. maybe_loadesi;
  1198. end;
  1199. end;
  1200. orddef:
  1201. begin
  1202. emit_const_ref(A_MOV,S_L,1,newreference(p.left.location.reference));
  1203. r:=newreference(p.left.location.reference);
  1204. inc(r^.offset,4);
  1205. if p.right.nodetype=ordconstn then
  1206. emit_const_ref(A_MOV,S_B,tordconstnode(p.right).value,r)
  1207. else
  1208. begin
  1209. case p.right.location.loc of
  1210. LOC_REGISTER,LOC_CREGISTER:
  1211. begin
  1212. emit_reg_ref(A_MOV,S_B,p.right.location.register,r);
  1213. ungetregister(p.right.location.register);
  1214. end;
  1215. LOC_MEM,LOC_REFERENCE:
  1216. begin
  1217. if not(R_EAX in unused) then
  1218. emit_reg(A_PUSH,S_L,R_EAX);
  1219. emit_ref_reg(A_MOV,S_B,newreference(p.right.location.reference),R_AL);
  1220. emit_reg_ref(A_MOV,S_B,R_AL,r);
  1221. if not(R_EAX in unused) then
  1222. emit_reg(A_POP,S_L,R_EAX);
  1223. del_reference(p.right.location.reference);
  1224. end
  1225. else
  1226. internalerror(20799);
  1227. end;
  1228. end;
  1229. end;
  1230. else
  1231. CGMessage(type_e_mismatch);
  1232. end;
  1233. end;
  1234. procedure loadansi2short(source,dest : tnode);
  1235. var
  1236. pushed : tpushed;
  1237. regs_to_push: byte;
  1238. begin
  1239. { Find out which registers have to be pushed (JM) }
  1240. regs_to_push := $ff;
  1241. remove_non_regvars_from_loc(source.location,regs_to_push);
  1242. { Push them (JM) }
  1243. pushusedregisters(pushed,regs_to_push);
  1244. case source.location.loc of
  1245. LOC_REFERENCE,LOC_MEM:
  1246. begin
  1247. { Now release the location and registers (see cgai386.pas: }
  1248. { loadansistring for more info on the order) (JM) }
  1249. ungetiftemp(source.location.reference);
  1250. del_reference(source.location.reference);
  1251. emit_push_mem(source.location.reference);
  1252. end;
  1253. LOC_REGISTER,LOC_CREGISTER:
  1254. begin
  1255. emit_reg(A_PUSH,S_L,source.location.register);
  1256. { Now release the register (JM) }
  1257. ungetregister32(source.location.register);
  1258. end;
  1259. end;
  1260. push_shortstring_length(dest);
  1261. emitpushreferenceaddr(dest.location.reference);
  1262. emitcall('FPC_ANSISTR_TO_SHORTSTR');
  1263. popusedregisters(pushed);
  1264. maybe_loadesi;
  1265. end;
  1266. end.
  1267. {
  1268. $Log$
  1269. Revision 1.3 2000-10-14 21:52:54 peter
  1270. * fixed memory leaks
  1271. Revision 1.2 2000/10/14 10:14:50 peter
  1272. * moehrendorf oct 2000 rewrite
  1273. Revision 1.1 2000/10/01 19:58:40 peter
  1274. * new file
  1275. }