cg386cnv.pas 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for type converting nodes
  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. {$ifdef TP}
  19. {$E+,F+,N+,D+,L+,Y+}
  20. {$endif}
  21. unit cg386cnv;
  22. interface
  23. uses
  24. tree;
  25. procedure loadshortstring(p:ptree);
  26. procedure loadlongstring(p:ptree);
  27. procedure loadansi2short(source,dest : ptree);
  28. procedure secondtypeconv(var p : ptree);
  29. procedure secondas(var p : ptree);
  30. procedure secondis(var p : ptree);
  31. implementation
  32. uses
  33. cobjects,verbose,globtype,globals,systems,
  34. symconst,symtable,aasm,types,
  35. hcodegen,temp_gen,pass_2,pass_1,
  36. cpubase,cpuasm,
  37. cgai386,tgeni386;
  38. procedure push_shortstring_length(p:ptree);
  39. var
  40. hightree : ptree;
  41. begin
  42. if is_open_string(p^.resulttype) then
  43. begin
  44. getsymonlyin(p^.symtable,'high'+pvarsym(p^.symtableentry)^.name);
  45. hightree:=genloadnode(pvarsym(srsym),p^.symtable);
  46. firstpass(hightree);
  47. secondpass(hightree);
  48. push_value_para(hightree,false,false,0,4);
  49. disposetree(hightree);
  50. end
  51. else
  52. begin
  53. push_int(pstringdef(p^.resulttype)^.len);
  54. end;
  55. end;
  56. procedure loadshortstring(p:ptree);
  57. {
  58. Load a string, handles stringdef and orddef (char) types
  59. }
  60. begin
  61. case p^.right^.resulttype^.deftype of
  62. stringdef:
  63. begin
  64. if (p^.right^.treetype=stringconstn) and
  65. (str_length(p^.right)=0) then
  66. emit_const_ref(
  67. A_MOV,S_B,0,newreference(p^.left^.location.reference))
  68. else
  69. begin
  70. emitpushreferenceaddr(p^.left^.location.reference);
  71. emitpushreferenceaddr(p^.right^.location.reference);
  72. push_shortstring_length(p^.left);
  73. emitcall('FPC_SHORTSTR_COPY');
  74. maybe_loadesi;
  75. end;
  76. end;
  77. orddef:
  78. begin
  79. if p^.right^.treetype=ordconstn then
  80. emit_const_ref(
  81. A_MOV,S_W,p^.right^.value*256+1,newreference(p^.left^.location.reference))
  82. else
  83. begin
  84. { not so elegant (goes better with extra register }
  85. {$ifndef noAllocEdi}
  86. getexplicitregister32(R_EDI);
  87. {$endif noAllocEdi}
  88. if (p^.right^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  89. begin
  90. emit_reg_reg(A_MOV,S_L,makereg32(p^.right^.location.register),R_EDI);
  91. ungetregister(p^.right^.location.register);
  92. end
  93. else
  94. begin
  95. emit_ref_reg(A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI);
  96. del_reference(p^.right^.location.reference);
  97. end;
  98. emit_const_reg(A_SHL,S_L,8,R_EDI);
  99. emit_const_reg(A_OR,S_L,1,R_EDI);
  100. emit_reg_ref(A_MOV,S_W,R_DI,newreference(p^.left^.location.reference));
  101. {$ifndef noAllocEdi}
  102. ungetregister32(R_EDI);
  103. {$endif noAllocEdi}
  104. end;
  105. end;
  106. else
  107. CGMessage(type_e_mismatch);
  108. end;
  109. end;
  110. procedure loadlongstring(p:ptree);
  111. {
  112. Load a string, handles stringdef and orddef (char) types
  113. }
  114. var
  115. r : preference;
  116. begin
  117. case p^.right^.resulttype^.deftype of
  118. stringdef:
  119. begin
  120. if (p^.right^.treetype=stringconstn) and
  121. (str_length(p^.right)=0) then
  122. emit_const_ref(A_MOV,S_L,0,newreference(p^.left^.location.reference))
  123. else
  124. begin
  125. emitpushreferenceaddr(p^.left^.location.reference);
  126. emitpushreferenceaddr(p^.right^.location.reference);
  127. push_shortstring_length(p^.left);
  128. emitcall('FPC_LONGSTR_COPY');
  129. maybe_loadesi;
  130. end;
  131. end;
  132. orddef:
  133. begin
  134. emit_const_ref(A_MOV,S_L,1,newreference(p^.left^.location.reference));
  135. r:=newreference(p^.left^.location.reference);
  136. inc(r^.offset,4);
  137. if p^.right^.treetype=ordconstn then
  138. emit_const_ref(A_MOV,S_B,p^.right^.value,r)
  139. else
  140. begin
  141. case p^.right^.location.loc of
  142. LOC_REGISTER,LOC_CREGISTER:
  143. begin
  144. emit_reg_ref(A_MOV,S_B,p^.right^.location.register,r);
  145. ungetregister(p^.right^.location.register);
  146. end;
  147. LOC_MEM,LOC_REFERENCE:
  148. begin
  149. if not(R_EAX in unused) then
  150. emit_reg(A_PUSH,S_L,R_EAX);
  151. emit_ref_reg(A_MOV,S_B,newreference(p^.right^.location.reference),R_AL);
  152. emit_reg_ref(A_MOV,S_B,R_AL,r);
  153. if not(R_EAX in unused) then
  154. emit_reg(A_POP,S_L,R_EAX);
  155. del_reference(p^.right^.location.reference);
  156. end
  157. else
  158. internalerror(20799);
  159. end;
  160. end;
  161. end;
  162. else
  163. CGMessage(type_e_mismatch);
  164. end;
  165. end;
  166. procedure loadansi2short(source,dest : ptree);
  167. var
  168. pushed : tpushed;
  169. begin
  170. del_reference(dest^.location.reference);
  171. case source^.location.loc of
  172. LOC_REFERENCE,LOC_MEM:
  173. begin
  174. ungetiftemp(source^.location.reference);
  175. {$IfNDef regallocfix}
  176. del_reference(source^.location.reference);
  177. pushusedregisters(pushed,$ff);
  178. emit_push_mem(source^.location.reference);
  179. {$Else regallocfix}
  180. pushusedregisters(pushed,$ff
  181. xor ($80 shr byte(source^.location.reference.base))
  182. xor ($80 shr byte(source^.location.reference.index)));
  183. emit_push_mem(source^.location.reference);
  184. del_reference(source^.location.reference);
  185. {$EndIf regallocfix}
  186. end;
  187. LOC_REGISTER,LOC_CREGISTER:
  188. begin
  189. {$IfNDef regallocfix}
  190. ungetregister32(source^.location.register);
  191. pushusedregisters(pushed,$ff);
  192. emit_reg(A_PUSH,S_L,source^.location.register);
  193. {$Else regallocfix}
  194. pushusedregisters(pushed, $ff xor ($80 shr byte(source^.location.register)));
  195. emit_reg(A_PUSH,S_L,source^.location.register);
  196. ungetregister32(source^.location.register);
  197. {$EndIf regallocfix}
  198. end;
  199. end;
  200. push_shortstring_length(dest);
  201. emitpushreferenceaddr(dest^.location.reference);
  202. emitcall('FPC_ANSISTR_TO_SHORTSTR');
  203. popusedregisters(pushed);
  204. maybe_loadesi;
  205. end;
  206. {*****************************************************************************
  207. SecondTypeConv
  208. *****************************************************************************}
  209. type
  210. tsecondconvproc = procedure(var pto,pfrom : ptree;convtyp : tconverttype);
  211. procedure second_int_to_int(var pto,pfrom : ptree;convtyp : tconverttype);
  212. var
  213. op : tasmop;
  214. opsize : topsize;
  215. hregister,
  216. hregister2 : tregister;
  217. l : pasmlabel;
  218. begin
  219. { insert range check if not explicit conversion }
  220. if not(pto^.explizit) then
  221. emitrangecheck(pfrom,pto^.resulttype);
  222. { is the result size smaller ? }
  223. if pto^.resulttype^.size<pfrom^.resulttype^.size then
  224. begin
  225. { only need to set the new size of a register }
  226. if (pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  227. begin
  228. case pto^.resulttype^.size of
  229. 1 : pto^.location.register:=makereg8(pfrom^.location.register);
  230. 2 : pto^.location.register:=makereg16(pfrom^.location.register);
  231. 4 : pto^.location.register:=makereg32(pfrom^.location.register);
  232. end;
  233. { we can release the upper register }
  234. if is_64bitint(pfrom^.resulttype) then
  235. ungetregister32(pfrom^.location.registerhigh);
  236. end;
  237. end
  238. { is the result size bigger ? }
  239. else if pto^.resulttype^.size>pfrom^.resulttype^.size then
  240. begin
  241. { remove reference }
  242. if not(pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  243. begin
  244. del_reference(pfrom^.location.reference);
  245. { we can do this here as we need no temp inside }
  246. ungetiftemp(pfrom^.location.reference);
  247. end;
  248. { get op and opsize, handle separate for constants, because
  249. movz doesn't support constant values }
  250. if (pfrom^.location.loc=LOC_MEM) and (pfrom^.location.reference.is_immediate) then
  251. begin
  252. if is_64bitint(pto^.resulttype) then
  253. opsize:=S_L
  254. else
  255. opsize:=def_opsize(pto^.resulttype);
  256. op:=A_MOV;
  257. end
  258. else
  259. begin
  260. opsize:=def2def_opsize(pfrom^.resulttype,pto^.resulttype);
  261. if opsize in [S_B,S_W,S_L] then
  262. op:=A_MOV
  263. else
  264. if is_signed(pfrom^.resulttype) then
  265. op:=A_MOVSX
  266. else
  267. op:=A_MOVZX;
  268. end;
  269. { load the register we need }
  270. if pfrom^.location.loc<>LOC_REGISTER then
  271. hregister:=getregister32
  272. else
  273. hregister:=pfrom^.location.register;
  274. { set the correct register size and location }
  275. clear_location(pto^.location);
  276. pto^.location.loc:=LOC_REGISTER;
  277. { do we need a second register for a 64 bit type ? }
  278. if is_64bitint(pto^.resulttype) then
  279. begin
  280. hregister2:=getregister32;
  281. pto^.location.registerhigh:=hregister2;
  282. end;
  283. case pto^.resulttype^.size of
  284. 1:
  285. pto^.location.register:=makereg8(hregister);
  286. 2:
  287. pto^.location.register:=makereg16(hregister);
  288. 4,8:
  289. pto^.location.register:=makereg32(hregister);
  290. end;
  291. { insert the assembler code }
  292. if pfrom^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  293. emit_reg_reg(op,opsize,pfrom^.location.register,pto^.location.register)
  294. else
  295. emit_ref_reg(op,opsize,
  296. newreference(pfrom^.location.reference),pto^.location.register);
  297. { do we need a sign extension for int64? }
  298. if is_64bitint(pto^.resulttype) then
  299. begin
  300. emit_reg_reg(A_XOR,S_L,
  301. hregister2,hregister2);
  302. if (porddef(pto^.resulttype)^.typ=s64bit) and
  303. is_signed(pfrom^.resulttype) then
  304. begin
  305. getlabel(l);
  306. emit_const_reg(A_TEST,S_L,$80000000,makereg32(hregister));
  307. emitjmp(C_Z,l);
  308. emit_reg(A_NOT,S_L,
  309. hregister2);
  310. emitlab(l);
  311. end;
  312. end;
  313. end;
  314. end;
  315. procedure second_string_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  316. var
  317. pushed : tpushed;
  318. begin
  319. { does anybody know a better solution than this big case statement ? }
  320. { ok, a proc table would do the job }
  321. case pstringdef(pto^.resulttype)^.string_typ of
  322. st_shortstring:
  323. case pstringdef(pfrom^.resulttype)^.string_typ of
  324. st_shortstring:
  325. begin
  326. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  327. copyshortstring(pto^.location.reference,pfrom^.location.reference,
  328. pstringdef(pto^.resulttype)^.len,false,true);
  329. { done by copyshortstring now (JM) }
  330. { del_reference(pfrom^.location.reference); }
  331. ungetiftemp(pfrom^.location.reference);
  332. end;
  333. st_longstring:
  334. begin
  335. {!!!!!!!}
  336. internalerror(8888);
  337. end;
  338. st_ansistring:
  339. begin
  340. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  341. loadansi2short(pfrom,pto);
  342. { this is done in secondtypeconv (FK)
  343. removetemps(exprasmlist,temptoremove);
  344. destroys:=true;
  345. }
  346. end;
  347. st_widestring:
  348. begin
  349. {!!!!!!!}
  350. internalerror(8888);
  351. end;
  352. end;
  353. st_longstring:
  354. case pstringdef(pfrom^.resulttype)^.string_typ of
  355. st_shortstring:
  356. begin
  357. {!!!!!!!}
  358. internalerror(8888);
  359. end;
  360. st_ansistring:
  361. begin
  362. {!!!!!!!}
  363. internalerror(8888);
  364. end;
  365. st_widestring:
  366. begin
  367. {!!!!!!!}
  368. internalerror(8888);
  369. end;
  370. end;
  371. st_ansistring:
  372. case pstringdef(pfrom^.resulttype)^.string_typ of
  373. st_shortstring:
  374. begin
  375. clear_location(pto^.location);
  376. pto^.location.loc:=LOC_REFERENCE;
  377. gettempansistringreference(pto^.location.reference);
  378. decrstringref(cansistringdef,pto^.location.reference);
  379. pushusedregisters(pushed,$ff);
  380. emit_push_lea_loc(pfrom^.location,true);
  381. emit_push_lea_loc(pto^.location,false);
  382. emitcall('FPC_SHORTSTR_TO_ANSISTR');
  383. maybe_loadesi;
  384. popusedregisters(pushed);
  385. end;
  386. st_longstring:
  387. begin
  388. {!!!!!!!}
  389. internalerror(8888);
  390. end;
  391. st_widestring:
  392. begin
  393. {!!!!!!!}
  394. internalerror(8888);
  395. end;
  396. end;
  397. st_widestring:
  398. case pstringdef(pfrom^.resulttype)^.string_typ of
  399. st_shortstring:
  400. begin
  401. {!!!!!!!}
  402. internalerror(8888);
  403. end;
  404. st_longstring:
  405. begin
  406. {!!!!!!!}
  407. internalerror(8888);
  408. end;
  409. st_ansistring:
  410. begin
  411. {!!!!!!!}
  412. internalerror(8888);
  413. end;
  414. st_widestring:
  415. begin
  416. {!!!!!!!}
  417. internalerror(8888);
  418. end;
  419. end;
  420. end;
  421. end;
  422. procedure second_cstring_to_pchar(var pto,pfrom : ptree;convtyp : tconverttype);
  423. var
  424. hr : preference;
  425. begin
  426. clear_location(pto^.location);
  427. pto^.location.loc:=LOC_REGISTER;
  428. pto^.location.register:=getregister32;
  429. case pstringdef(pfrom^.resulttype)^.string_typ of
  430. st_shortstring :
  431. begin
  432. inc(pfrom^.location.reference.offset);
  433. emit_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  434. pto^.location.register);
  435. end;
  436. st_ansistring :
  437. begin
  438. if (pfrom^.treetype=stringconstn) and
  439. (str_length(pfrom)=0) then
  440. begin
  441. new(hr);
  442. reset_reference(hr^);
  443. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  444. emit_ref_reg(A_LEA,S_L,hr,pto^.location.register);
  445. end
  446. else
  447. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  448. pto^.location.register);
  449. end;
  450. st_longstring:
  451. begin
  452. {!!!!!!!}
  453. internalerror(8888);
  454. end;
  455. st_widestring:
  456. begin
  457. {!!!!!!!}
  458. internalerror(8888);
  459. end;
  460. end;
  461. end;
  462. procedure second_string_to_chararray(var pto,pfrom : ptree;convtyp : tconverttype);
  463. var
  464. l1 : pasmlabel;
  465. hr : preference;
  466. begin
  467. case pstringdef(pfrom^.resulttype)^.string_typ of
  468. st_shortstring :
  469. begin
  470. inc(pto^.location.reference.offset);
  471. end;
  472. st_ansistring :
  473. begin
  474. clear_location(pto^.location);
  475. pto^.location.loc:=LOC_REFERENCE;
  476. reset_reference(pto^.location.reference);
  477. getlabel(l1);
  478. case pfrom^.location.loc of
  479. LOC_CREGISTER,LOC_REGISTER:
  480. pto^.location.reference.base:=pfrom^.location.register;
  481. LOC_MEM,LOC_REFERENCE:
  482. begin
  483. pto^.location.reference.base:=getregister32;
  484. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  485. pto^.location.reference.base);
  486. del_reference(pfrom^.location.reference);
  487. end;
  488. end;
  489. emit_const_reg(A_CMP,S_L,0,pto^.location.reference.base);
  490. emitjmp(C_NZ,l1);
  491. new(hr);
  492. reset_reference(hr^);
  493. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  494. emit_ref_reg(A_LEA,S_L,hr,pto^.location.reference.base);
  495. emitlab(l1);
  496. end;
  497. st_longstring:
  498. begin
  499. {!!!!!!!}
  500. internalerror(8888);
  501. end;
  502. st_widestring:
  503. begin
  504. {!!!!!!!}
  505. internalerror(8888);
  506. end;
  507. end;
  508. end;
  509. procedure second_array_to_pointer(var pto,pfrom : ptree;convtyp : tconverttype);
  510. begin
  511. del_reference(pfrom^.location.reference);
  512. clear_location(pto^.location);
  513. pto^.location.loc:=LOC_REGISTER;
  514. pto^.location.register:=getregister32;
  515. emit_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  516. pto^.location.register);
  517. end;
  518. procedure second_pointer_to_array(var pto,pfrom : ptree;convtyp : tconverttype);
  519. begin
  520. clear_location(pto^.location);
  521. pto^.location.loc:=LOC_REFERENCE;
  522. reset_reference(pto^.location.reference);
  523. case pfrom^.location.loc of
  524. LOC_REGISTER :
  525. pto^.location.reference.base:=pfrom^.location.register;
  526. LOC_CREGISTER :
  527. begin
  528. pto^.location.reference.base:=getregister32;
  529. emit_reg_reg(A_MOV,S_L,pfrom^.location.register,pto^.location.reference.base);
  530. end
  531. else
  532. begin
  533. del_reference(pfrom^.location.reference);
  534. pto^.location.reference.base:=getregister32;
  535. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  536. pto^.location.reference.base);
  537. end;
  538. end;
  539. end;
  540. { generates the code for the type conversion from an array of char }
  541. { to a string }
  542. procedure second_chararray_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  543. var
  544. pushed : tpushed;
  545. l : longint;
  546. begin
  547. { calc the length of the array }
  548. l:=parraydef(pfrom^.resulttype)^.highrange-parraydef(pfrom^.resulttype)^.lowrange+1;
  549. { this is a type conversion which copies the data, so we can't }
  550. { return a reference }
  551. clear_location(pto^.location);
  552. pto^.location.loc:=LOC_MEM;
  553. case pstringdef(pto^.resulttype)^.string_typ of
  554. st_shortstring :
  555. begin
  556. if l>255 then
  557. begin
  558. CGMessage(type_e_mismatch);
  559. l:=255;
  560. end;
  561. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  562. pushusedregisters(pushed,$ff);
  563. if l>=pto^.resulttype^.size then
  564. push_int(pto^.resulttype^.size-1)
  565. else
  566. push_int(l);
  567. { we've also to release the registers ... }
  568. del_reference(pfrom^.location.reference);
  569. { ... here only the temp. location is released }
  570. emit_push_lea_loc(pfrom^.location,true);
  571. emitpushreferenceaddr(pto^.location.reference);
  572. emitcall('FPC_CHARARRAY_TO_SHORTSTR');
  573. maybe_loadesi;
  574. popusedregisters(pushed);
  575. end;
  576. st_ansistring :
  577. begin
  578. gettempansistringreference(pto^.location.reference);
  579. decrstringref(cansistringdef,pto^.location.reference);
  580. release_loc(pfrom^.location);
  581. pushusedregisters(pushed,$ff);
  582. push_int(l);
  583. emitpushreferenceaddr(pfrom^.location.reference);
  584. emitpushreferenceaddr(pto^.location.reference);
  585. emitcall('FPC_CHARARRAY_TO_ANSISTR');
  586. popusedregisters(pushed);
  587. maybe_loadesi;
  588. end;
  589. st_longstring:
  590. begin
  591. {!!!!!!!}
  592. internalerror(8888);
  593. end;
  594. st_widestring:
  595. begin
  596. {!!!!!!!}
  597. internalerror(8888);
  598. end;
  599. end;
  600. end;
  601. procedure second_char_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  602. var
  603. pushed : tpushed;
  604. begin
  605. clear_location(pto^.location);
  606. pto^.location.loc:=LOC_MEM;
  607. case pstringdef(pto^.resulttype)^.string_typ of
  608. st_shortstring :
  609. begin
  610. gettempofsizereference(256,pto^.location.reference);
  611. { call loadstring with correct left and right }
  612. pto^.right:=pfrom;
  613. pto^.left:=pto;
  614. loadshortstring(pto);
  615. pto^.left:=nil; { reset left tree, which is empty }
  616. { pto^.right is not disposed for typeconv !! PM }
  617. disposetree(pto^.right);
  618. pto^.right:=nil;
  619. end;
  620. st_ansistring :
  621. begin
  622. gettempansistringreference(pto^.location.reference);
  623. decrstringref(cansistringdef,pto^.location.reference);
  624. release_loc(pfrom^.location);
  625. pushusedregisters(pushed,$ff);
  626. emit_pushw_loc(pfrom^.location);
  627. emitpushreferenceaddr(pto^.location.reference);
  628. emitcall('FPC_CHAR_TO_ANSISTR');
  629. popusedregisters(pushed);
  630. maybe_loadesi;
  631. end;
  632. else
  633. internalerror(4179);
  634. end;
  635. end;
  636. procedure second_int_to_real(var pto,pfrom : ptree;convtyp : tconverttype);
  637. var
  638. r : preference;
  639. hregister : tregister;
  640. l1,l2 : pasmlabel;
  641. begin
  642. { for u32bit a solution is to push $0 and to load a comp }
  643. { does this first, it destroys maybe EDI }
  644. hregister:=R_EDI;
  645. if porddef(pfrom^.resulttype)^.typ=u32bit then
  646. push_int(0);
  647. if (pfrom^.location.loc=LOC_REGISTER) or
  648. (pfrom^.location.loc=LOC_CREGISTER) then
  649. begin
  650. {$ifndef noAllocEdi}
  651. if not (porddef(pfrom^.resulttype)^.typ in [u32bit,s32bit,u64bit,s64bit]) then
  652. getexplicitregister32(R_EDI);
  653. {$endif noAllocEdi}
  654. case porddef(pfrom^.resulttype)^.typ of
  655. s8bit : emit_reg_reg(A_MOVSX,S_BL,pfrom^.location.register,R_EDI);
  656. u8bit : emit_reg_reg(A_MOVZX,S_BL,pfrom^.location.register,R_EDI);
  657. s16bit : emit_reg_reg(A_MOVSX,S_WL,pfrom^.location.register,R_EDI);
  658. u16bit : emit_reg_reg(A_MOVZX,S_WL,pfrom^.location.register,R_EDI);
  659. u32bit,s32bit:
  660. hregister:=pfrom^.location.register;
  661. u64bit,s64bit:
  662. begin
  663. emit_reg(A_PUSH,S_L,pfrom^.location.registerhigh);
  664. hregister:=pfrom^.location.registerlow;
  665. end;
  666. end;
  667. ungetregister(pfrom^.location.register);
  668. end
  669. else
  670. begin
  671. r:=newreference(pfrom^.location.reference);
  672. {$ifndef noAllocEdi}
  673. getexplicitregister32(R_EDI);
  674. {$endif noAllocEdi}
  675. case porddef(pfrom^.resulttype)^.typ of
  676. s8bit:
  677. emit_ref_reg(A_MOVSX,S_BL,r,R_EDI);
  678. u8bit:
  679. emit_ref_reg(A_MOVZX,S_BL,r,R_EDI);
  680. s16bit:
  681. emit_ref_reg(A_MOVSX,S_WL,r,R_EDI);
  682. u16bit:
  683. emit_ref_reg(A_MOVZX,S_WL,r,R_EDI);
  684. u32bit,s32bit:
  685. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  686. u64bit,s64bit:
  687. begin
  688. inc(r^.offset,4);
  689. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  690. emit_reg(A_PUSH,S_L,R_EDI);
  691. r:=newreference(pfrom^.location.reference);
  692. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  693. end;
  694. end;
  695. del_reference(pfrom^.location.reference);
  696. ungetiftemp(pfrom^.location.reference);
  697. end;
  698. { for 64 bit integers, the high dword is already pushed }
  699. emit_reg(A_PUSH,S_L,hregister);
  700. {$ifndef noAllocEdi}
  701. if hregister = R_EDI then
  702. ungetregister32(R_EDI);
  703. {$endif noAllocEdi}
  704. r:=new_reference(R_ESP,0);
  705. case porddef(pfrom^.resulttype)^.typ of
  706. u32bit:
  707. begin
  708. emit_ref(A_FILD,S_IQ,r);
  709. emit_const_reg(A_ADD,S_L,8,R_ESP);
  710. end;
  711. s64bit:
  712. begin
  713. emit_ref(A_FILD,S_IQ,r);
  714. emit_const_reg(A_ADD,S_L,8,R_ESP);
  715. end;
  716. u64bit:
  717. begin
  718. { unsigned 64 bit ints are harder to handle: }
  719. { we load bits 0..62 and then check bit 63: }
  720. { if it is 1 then we add $80000000 000000000 }
  721. { as double }
  722. inc(r^.offset,4);
  723. {$ifndef noAllocEdi}
  724. getexplicitregister32(R_EDI);
  725. {$endif noAllocEdi}
  726. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  727. r:=new_reference(R_ESP,4);
  728. emit_const_ref(A_AND,S_L,$7fffffff,r);
  729. emit_const_reg(A_TEST,S_L,$80000000,R_EDI);
  730. {$ifndef noAllocEdi}
  731. ungetregister32(R_EDI);
  732. {$endif noAllocEdi}
  733. r:=new_reference(R_ESP,0);
  734. emit_ref(A_FILD,S_IQ,r);
  735. getdatalabel(l1);
  736. getlabel(l2);
  737. emitjmp(C_Z,l2);
  738. consts^.concat(new(pai_label,init(l1)));
  739. { I got this constant from a test progtram (FK) }
  740. consts^.concat(new(pai_const,init_32bit(0)));
  741. consts^.concat(new(pai_const,init_32bit(1138753536)));
  742. r:=new_reference(R_NO,0);
  743. r^.symbol:=l1;
  744. emit_ref(A_FADD,S_FL,r);
  745. emitlab(l2);
  746. emit_const_reg(A_ADD,S_L,8,R_ESP);
  747. end
  748. else
  749. begin
  750. emit_ref(A_FILD,S_IL,r);
  751. {$ifndef noAllocEdi}
  752. getexplicitregister32(R_EDI);
  753. {$endif noAllocEdi}
  754. emit_reg(A_POP,S_L,R_EDI);
  755. {$ifndef noAllocEdi}
  756. ungetregister32(R_EDI);
  757. {$endif noAllocEdi}
  758. end;
  759. end;
  760. inc(fpuvaroffset);
  761. clear_location(pto^.location);
  762. pto^.location.loc:=LOC_FPU;
  763. end;
  764. procedure second_real_to_fix(var pto,pfrom : ptree;convtyp : tconverttype);
  765. var
  766. rreg : tregister;
  767. ref : treference;
  768. begin
  769. { real must be on fpu stack }
  770. if (pfrom^.location.loc<>LOC_FPU) then
  771. emit_ref(A_FLD,S_FL,newreference(pfrom^.location.reference));
  772. push_int($1f3f);
  773. push_int(65536);
  774. reset_reference(ref);
  775. ref.base:=R_ESP;
  776. emit_ref(A_FIMUL,S_IL,newreference(ref));
  777. ref.offset:=4;
  778. emit_ref(A_FSTCW,S_NO,newreference(ref));
  779. ref.offset:=6;
  780. emit_ref(A_FLDCW,S_NO,newreference(ref));
  781. ref.offset:=0;
  782. emit_ref(A_FISTP,S_IL,newreference(ref));
  783. ref.offset:=4;
  784. emit_ref(A_FLDCW,S_NO,newreference(ref));
  785. rreg:=getregister32;
  786. emit_reg(A_POP,S_L,rreg);
  787. { better than an add on all processors }
  788. {$ifndef noAllocEdi}
  789. getexplicitregister32(R_EDI);
  790. {$endif noAllocEdi}
  791. emit_reg(A_POP,S_L,R_EDI);
  792. {$ifndef noAllocEdi}
  793. ungetregister32(R_EDI);
  794. {$endif noAllocEdi}
  795. clear_location(pto^.location);
  796. pto^.location.loc:=LOC_REGISTER;
  797. pto^.location.register:=rreg;
  798. inc(fpuvaroffset);
  799. end;
  800. procedure second_real_to_real(var pto,pfrom : ptree;convtyp : tconverttype);
  801. begin
  802. case pfrom^.location.loc of
  803. LOC_FPU : ;
  804. LOC_CFPUREGISTER:
  805. begin
  806. pto^.location:=pfrom^.location;
  807. exit;
  808. end;
  809. LOC_MEM,
  810. LOC_REFERENCE:
  811. begin
  812. floatload(pfloatdef(pfrom^.resulttype)^.typ,
  813. pfrom^.location.reference);
  814. { we have to free the reference }
  815. del_reference(pfrom^.location.reference);
  816. end;
  817. end;
  818. clear_location(pto^.location);
  819. pto^.location.loc:=LOC_FPU;
  820. end;
  821. procedure second_fix_to_real(var pto,pfrom : ptree;convtyp : tconverttype);
  822. var
  823. popeax,popebx,popecx,popedx : boolean;
  824. startreg : tregister;
  825. hl : pasmlabel;
  826. r : treference;
  827. begin
  828. if (pfrom^.location.loc=LOC_REGISTER) or
  829. (pfrom^.location.loc=LOC_CREGISTER) then
  830. begin
  831. startreg:=pfrom^.location.register;
  832. ungetregister(startreg);
  833. popeax:=(startreg<>R_EAX) and not (R_EAX in unused);
  834. if popeax then
  835. emit_reg(A_PUSH,S_L,R_EAX);
  836. { mov eax,eax is removed by emit_reg_reg }
  837. emit_reg_reg(A_MOV,S_L,startreg,R_EAX);
  838. end
  839. else
  840. begin
  841. emit_ref_reg(A_MOV,S_L,newreference(
  842. pfrom^.location.reference),R_EAX);
  843. del_reference(pfrom^.location.reference);
  844. startreg:=R_NO;
  845. end;
  846. popebx:=(startreg<>R_EBX) and not (R_EBX in unused);
  847. if popebx then
  848. emit_reg(A_PUSH,S_L,R_EBX);
  849. popecx:=(startreg<>R_ECX) and not (R_ECX in unused);
  850. if popecx then
  851. emit_reg(A_PUSH,S_L,R_ECX);
  852. popedx:=(startreg<>R_EDX) and not (R_EDX in unused);
  853. if popedx then
  854. emit_reg(A_PUSH,S_L,R_EDX);
  855. emit_none(A_CDQ,S_NO);
  856. emit_reg_reg(A_XOR,S_L,R_EDX,R_EAX);
  857. emit_reg_reg(A_MOV,S_L,R_EAX,R_EBX);
  858. emit_reg_reg(A_SUB,S_L,R_EDX,R_EAX);
  859. getlabel(hl);
  860. emitjmp(C_Z,hl);
  861. emit_const_reg(A_RCL,S_L,1,R_EBX);
  862. emit_reg_reg(A_BSR,S_L,R_EAX,R_EDX);
  863. emit_const_reg(A_MOV,S_B,32,R_CL);
  864. emit_reg_reg(A_SUB,S_B,R_DL,R_CL);
  865. emit_reg_reg(A_SHL,S_L,R_CL,R_EAX);
  866. emit_const_reg(A_ADD,S_W,1007,R_DX);
  867. emit_const_reg(A_SHL,S_W,5,R_DX);
  868. emit_const_reg_reg(A_SHLD,S_W,11,R_DX,R_BX);
  869. emit_const_reg_reg(A_SHLD,S_L,20,R_EAX,R_EBX);
  870. emit_const_reg(A_SHL,S_L,20,R_EAX);
  871. emitlab(hl);
  872. { better than an add on all processors }
  873. emit_reg(A_PUSH,S_L,R_EBX);
  874. emit_reg(A_PUSH,S_L,R_EAX);
  875. reset_reference(r);
  876. r.base:=R_ESP;
  877. emit_ref(A_FLD,S_FL,newreference(r));
  878. emit_const_reg(A_ADD,S_L,8,R_ESP);
  879. if popedx then
  880. emit_reg(A_POP,S_L,R_EDX);
  881. if popecx then
  882. emit_reg(A_POP,S_L,R_ECX);
  883. if popebx then
  884. emit_reg(A_POP,S_L,R_EBX);
  885. if popeax then
  886. emit_reg(A_POP,S_L,R_EAX);
  887. clear_location(pto^.location);
  888. pto^.location.loc:=LOC_FPU;
  889. end;
  890. procedure second_cord_to_pointer(var pto,pfrom : ptree;convtyp : tconverttype);
  891. begin
  892. { this can't happend, because constants are already processed in
  893. pass 1 }
  894. internalerror(47423985);
  895. end;
  896. procedure second_int_to_fix(var pto,pfrom : ptree;convtyp : tconverttype);
  897. var
  898. hregister : tregister;
  899. begin
  900. if (pfrom^.location.loc=LOC_REGISTER) then
  901. hregister:=pfrom^.location.register
  902. else if (pfrom^.location.loc=LOC_CREGISTER) then
  903. hregister:=getregister32
  904. else
  905. begin
  906. del_reference(pfrom^.location.reference);
  907. hregister:=getregister32;
  908. case porddef(pfrom^.resulttype)^.typ of
  909. s8bit : emit_ref_reg(A_MOVSX,S_BL,newreference(pfrom^.location.reference),
  910. hregister);
  911. u8bit : emit_ref_reg(A_MOVZX,S_BL,newreference(pfrom^.location.reference),
  912. hregister);
  913. s16bit : emit_ref_reg(A_MOVSX,S_WL,newreference(pfrom^.location.reference),
  914. hregister);
  915. u16bit : emit_ref_reg(A_MOVZX,S_WL,newreference(pfrom^.location.reference),
  916. hregister);
  917. u32bit,s32bit : emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  918. hregister);
  919. {!!!! u32bit }
  920. end;
  921. end;
  922. emit_const_reg(A_SHL,S_L,16,hregister);
  923. clear_location(pto^.location);
  924. pto^.location.loc:=LOC_REGISTER;
  925. pto^.location.register:=hregister;
  926. end;
  927. procedure second_proc_to_procvar(var pto,pfrom : ptree;convtyp : tconverttype);
  928. begin
  929. { method pointer ? }
  930. if assigned(pfrom^.left) then
  931. begin
  932. set_location(pto^.location,pfrom^.location);
  933. end
  934. else
  935. begin
  936. clear_location(pto^.location);
  937. pto^.location.loc:=LOC_REGISTER;
  938. pto^.location.register:=getregister32;
  939. del_reference(pfrom^.location.reference);
  940. emit_ref_reg(A_LEA,S_L,
  941. newreference(pfrom^.location.reference),pto^.location.register);
  942. end;
  943. end;
  944. procedure second_bool_to_int(var pto,pfrom : ptree;convtyp : tconverttype);
  945. var
  946. oldtruelabel,oldfalselabel,hlabel : pasmlabel;
  947. hregister : tregister;
  948. newsize,
  949. opsize : topsize;
  950. op : tasmop;
  951. begin
  952. oldtruelabel:=truelabel;
  953. oldfalselabel:=falselabel;
  954. getlabel(truelabel);
  955. getlabel(falselabel);
  956. secondpass(pfrom);
  957. { byte(boolean) or word(wordbool) or longint(longbool) must
  958. be accepted for var parameters }
  959. if (pto^.explizit) and
  960. (pfrom^.resulttype^.size=pto^.resulttype^.size) and
  961. (pfrom^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  962. begin
  963. set_location(pto^.location,pfrom^.location);
  964. truelabel:=oldtruelabel;
  965. falselabel:=oldfalselabel;
  966. exit;
  967. end;
  968. clear_location(pto^.location);
  969. pto^.location.loc:=LOC_REGISTER;
  970. del_reference(pfrom^.location.reference);
  971. case pfrom^.resulttype^.size of
  972. 1 : begin
  973. case pto^.resulttype^.size of
  974. 1 : opsize:=S_B;
  975. 2 : opsize:=S_BW;
  976. 4 : opsize:=S_BL;
  977. end;
  978. end;
  979. 2 : begin
  980. case pto^.resulttype^.size of
  981. 1 : begin
  982. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  983. pfrom^.location.register:=reg16toreg8(pfrom^.location.register);
  984. opsize:=S_B;
  985. end;
  986. 2 : opsize:=S_W;
  987. 4 : opsize:=S_WL;
  988. end;
  989. end;
  990. 4 : begin
  991. case pto^.resulttype^.size of
  992. 1 : begin
  993. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  994. pfrom^.location.register:=reg32toreg8(pfrom^.location.register);
  995. opsize:=S_B;
  996. end;
  997. 2 : begin
  998. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  999. pfrom^.location.register:=reg32toreg16(pfrom^.location.register);
  1000. opsize:=S_W;
  1001. end;
  1002. 4 : opsize:=S_L;
  1003. end;
  1004. end;
  1005. end;
  1006. if opsize in [S_B,S_W,S_L] then
  1007. op:=A_MOV
  1008. else
  1009. if is_signed(pto^.resulttype) then
  1010. op:=A_MOVSX
  1011. else
  1012. op:=A_MOVZX;
  1013. hregister:=getregister32;
  1014. case pto^.resulttype^.size of
  1015. 1 : begin
  1016. pto^.location.register:=reg32toreg8(hregister);
  1017. newsize:=S_B;
  1018. end;
  1019. 2 : begin
  1020. pto^.location.register:=reg32toreg16(hregister);
  1021. newsize:=S_W;
  1022. end;
  1023. 4 : begin
  1024. pto^.location.register:=hregister;
  1025. newsize:=S_L;
  1026. end;
  1027. else
  1028. internalerror(10060);
  1029. end;
  1030. case pfrom^.location.loc of
  1031. LOC_MEM,
  1032. LOC_REFERENCE : emit_ref_reg(op,opsize,
  1033. newreference(pfrom^.location.reference),pto^.location.register);
  1034. LOC_REGISTER,
  1035. LOC_CREGISTER : begin
  1036. { remove things like movb %al,%al }
  1037. if pfrom^.location.register<>pto^.location.register then
  1038. emit_reg_reg(op,opsize,
  1039. pfrom^.location.register,pto^.location.register);
  1040. end;
  1041. LOC_FLAGS : begin
  1042. emit_flag2reg(pfrom^.location.resflags,pto^.location.register);
  1043. end;
  1044. LOC_JUMP : begin
  1045. getlabel(hlabel);
  1046. emitlab(truelabel);
  1047. emit_const_reg(A_MOV,newsize,1,pto^.location.register);
  1048. emitjmp(C_None,hlabel);
  1049. emitlab(falselabel);
  1050. emit_reg_reg(A_XOR,newsize,pto^.location.register,
  1051. pto^.location.register);
  1052. emitlab(hlabel);
  1053. end;
  1054. else
  1055. internalerror(10061);
  1056. end;
  1057. truelabel:=oldtruelabel;
  1058. falselabel:=oldfalselabel;
  1059. end;
  1060. procedure second_int_to_bool(var pto,pfrom : ptree;convtyp : tconverttype);
  1061. var
  1062. hregister : tregister;
  1063. flags : tresflags;
  1064. opsize : topsize;
  1065. begin
  1066. clear_location(pto^.location);
  1067. { byte(boolean) or word(wordbool) or longint(longbool) must
  1068. be accepted for var parameters }
  1069. if (pto^.explizit) and
  1070. (pfrom^.resulttype^.size=pto^.resulttype^.size) and
  1071. (pfrom^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  1072. begin
  1073. set_location(pto^.location,pfrom^.location);
  1074. exit;
  1075. end;
  1076. pto^.location.loc:=LOC_REGISTER;
  1077. del_reference(pfrom^.location.reference);
  1078. opsize:=def_opsize(pfrom^.resulttype);
  1079. case pfrom^.location.loc of
  1080. LOC_MEM,LOC_REFERENCE :
  1081. begin
  1082. hregister:=def_getreg(pfrom^.resulttype);
  1083. emit_ref_reg(A_MOV,opsize,
  1084. newreference(pfrom^.location.reference),hregister);
  1085. emit_reg_reg(A_OR,opsize,hregister,hregister);
  1086. flags:=F_NE;
  1087. end;
  1088. LOC_FLAGS :
  1089. begin
  1090. hregister:=getregister32;
  1091. flags:=pfrom^.location.resflags;
  1092. end;
  1093. LOC_REGISTER,LOC_CREGISTER :
  1094. begin
  1095. hregister:=pfrom^.location.register;
  1096. emit_reg_reg(A_OR,opsize,hregister,hregister);
  1097. flags:=F_NE;
  1098. end;
  1099. else
  1100. internalerror(10062);
  1101. end;
  1102. case pto^.resulttype^.size of
  1103. 1 : pto^.location.register:=makereg8(hregister);
  1104. 2 : pto^.location.register:=makereg16(hregister);
  1105. 4 : pto^.location.register:=makereg32(hregister);
  1106. else
  1107. internalerror(10064);
  1108. end;
  1109. emit_flag2reg(flags,pto^.location.register);
  1110. end;
  1111. procedure second_load_smallset(var pto,pfrom : ptree;convtyp : tconverttype);
  1112. var
  1113. href : treference;
  1114. pushedregs : tpushed;
  1115. begin
  1116. href.symbol:=nil;
  1117. pushusedregisters(pushedregs,$ff);
  1118. gettempofsizereference(32,href);
  1119. emitpushreferenceaddr(pfrom^.location.reference);
  1120. emitpushreferenceaddr(href);
  1121. emitcall('FPC_SET_LOAD_SMALL');
  1122. maybe_loadesi;
  1123. popusedregisters(pushedregs);
  1124. clear_location(pto^.location);
  1125. pto^.location.loc:=LOC_MEM;
  1126. pto^.location.reference:=href;
  1127. end;
  1128. procedure second_ansistring_to_pchar(var pto,pfrom : ptree;convtyp : tconverttype);
  1129. var
  1130. l1 : pasmlabel;
  1131. hr : preference;
  1132. begin
  1133. clear_location(pto^.location);
  1134. pto^.location.loc:=LOC_REGISTER;
  1135. getlabel(l1);
  1136. case pfrom^.location.loc of
  1137. LOC_CREGISTER,LOC_REGISTER:
  1138. pto^.location.register:=pfrom^.location.register;
  1139. LOC_MEM,LOC_REFERENCE:
  1140. begin
  1141. pto^.location.register:=getregister32;
  1142. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  1143. pto^.location.register);
  1144. del_reference(pfrom^.location.reference);
  1145. end;
  1146. end;
  1147. emit_const_reg(A_CMP,S_L,0,pto^.location.register);
  1148. emitjmp(C_NZ,l1);
  1149. new(hr);
  1150. reset_reference(hr^);
  1151. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  1152. emit_ref_reg(A_LEA,S_L,hr,pto^.location.register);
  1153. emitlab(l1);
  1154. end;
  1155. procedure second_pchar_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  1156. var
  1157. pushed : tpushed;
  1158. begin
  1159. case pstringdef(pto^.resulttype)^.string_typ of
  1160. st_shortstring:
  1161. begin
  1162. pto^.location.loc:=LOC_REFERENCE;
  1163. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  1164. pushusedregisters(pushed,$ff);
  1165. case pfrom^.location.loc of
  1166. LOC_REGISTER,LOC_CREGISTER:
  1167. begin
  1168. emit_reg(A_PUSH,S_L,pfrom^.location.register);
  1169. ungetregister32(pfrom^.location.register);
  1170. end;
  1171. LOC_REFERENCE,LOC_MEM:
  1172. begin
  1173. emit_push_mem(pfrom^.location.reference);
  1174. del_reference(pfrom^.location.reference);
  1175. end;
  1176. end;
  1177. emitpushreferenceaddr(pto^.location.reference);
  1178. emitcall('FPC_PCHAR_TO_SHORTSTR');
  1179. maybe_loadesi;
  1180. popusedregisters(pushed);
  1181. end;
  1182. st_ansistring:
  1183. begin
  1184. pto^.location.loc:=LOC_REFERENCE;
  1185. gettempansistringreference(pto^.location.reference);
  1186. decrstringref(cansistringdef,pto^.location.reference);
  1187. case pfrom^.location.loc of
  1188. LOC_REFERENCE,LOC_MEM:
  1189. begin
  1190. {$IfNDef regallocfix}
  1191. del_reference(pfrom^.location.reference);
  1192. pushusedregisters(pushed,$ff);
  1193. emit_push_mem(pfrom^.location.reference);
  1194. {$Else regallocfix}
  1195. pushusedregisters(pushed,$ff
  1196. xor ($80 shr byte(pfrom^.location.reference.base))
  1197. xor ($80 shr byte(pfrom^.location.reference.index)));
  1198. emit_push_mem(pfrom^.location.reference);
  1199. del_reference(pfrom^.location.reference);
  1200. {$EndIf regallocfix}
  1201. end;
  1202. LOC_REGISTER,LOC_CREGISTER:
  1203. begin
  1204. {$IfNDef regallocfix}
  1205. ungetregister32(pfrom^.location.register);
  1206. pushusedregisters(pushed,$ff);
  1207. emit_reg(A_PUSH,S_L,pfrom^.location.register);
  1208. {$Else regallocfix}
  1209. pushusedregisters(pushed, $ff xor ($80 shr byte(pfrom^.location.register)));
  1210. emit_reg(A_PUSH,S_L,pfrom^.location.register);
  1211. ungetregister32(pfrom^.location.register);
  1212. {$EndIf regallocfix}
  1213. end;
  1214. end;
  1215. emitpushreferenceaddr(pto^.location.reference);
  1216. emitcall('FPC_PCHAR_TO_ANSISTR');
  1217. maybe_loadesi;
  1218. popusedregisters(pushed);
  1219. end;
  1220. else
  1221. begin
  1222. internalerror(12121);
  1223. end;
  1224. end;
  1225. end;
  1226. procedure second_nothing(var pto,pfrom : ptree;convtyp : tconverttype);
  1227. begin
  1228. end;
  1229. {****************************************************************************
  1230. SecondTypeConv
  1231. ****************************************************************************}
  1232. procedure secondtypeconv(var p : ptree);
  1233. const
  1234. secondconvert : array[tconverttype] of tsecondconvproc = (
  1235. second_nothing, {equal}
  1236. second_nothing, {not_possible}
  1237. second_string_to_string,
  1238. second_char_to_string,
  1239. second_pchar_to_string,
  1240. second_nothing, {cchar_to_pchar}
  1241. second_cstring_to_pchar,
  1242. second_ansistring_to_pchar,
  1243. second_string_to_chararray,
  1244. second_chararray_to_string,
  1245. second_array_to_pointer,
  1246. second_pointer_to_array,
  1247. second_int_to_int,
  1248. second_int_to_bool,
  1249. second_bool_to_int, { bool_to_bool }
  1250. second_bool_to_int,
  1251. second_real_to_real,
  1252. second_int_to_real,
  1253. second_int_to_fix,
  1254. second_real_to_fix,
  1255. second_fix_to_real,
  1256. second_proc_to_procvar,
  1257. second_nothing, {arrayconstructor_to_set}
  1258. second_load_smallset,
  1259. second_cord_to_pointer
  1260. );
  1261. {$ifdef TESTOBJEXT2}
  1262. var
  1263. r : preference;
  1264. nillabel : plabel;
  1265. {$endif TESTOBJEXT2}
  1266. begin
  1267. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1268. { type conversion (FK) }
  1269. if not(p^.convtyp in [tc_bool_2_int,tc_bool_2_bool]) then
  1270. begin
  1271. secondpass(p^.left);
  1272. set_location(p^.location,p^.left^.location);
  1273. if codegenerror then
  1274. exit;
  1275. end;
  1276. { the second argument only is for maybe_range_checking !}
  1277. secondconvert[p^.convtyp](p,p^.left,p^.convtyp);
  1278. {$ifdef TESTOBJEXT2}
  1279. { Check explicit conversions to objects pointers !! }
  1280. if p^.explizit and
  1281. (p^.resulttype^.deftype=pointerdef) and
  1282. (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) and not
  1283. (pobjectdef(ppointerdef(p^.resulttype)^.definition)^.isclass) and
  1284. ((pobjectdef(ppointerdef(p^.resulttype)^.definition)^.options and oo_hasvmt)<>0) and
  1285. (cs_check_range in aktlocalswitches) then
  1286. begin
  1287. new(r);
  1288. reset_reference(r^);
  1289. if p^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1290. r^.base:=p^.location.register
  1291. else
  1292. begin
  1293. {$ifndef noAllocEdi}
  1294. getexplicitregister32(R_EDI);
  1295. {$endif noAllocEdi}
  1296. emit_mov_loc_reg(p^.location,R_EDI);
  1297. r^.base:=R_EDI;
  1298. end;
  1299. { NIL must be accepted !! }
  1300. emit_reg_reg(A_OR,S_L,r^.base,r^.base);
  1301. {$ifndef noAllocEdi}
  1302. ungetregister32(R_EDI);
  1303. {$endif noAllocEdi}
  1304. getlabel(nillabel);
  1305. emitjmp(C_E,nillabel);
  1306. { this is one point where we need vmt_offset (PM) }
  1307. r^.offset:= pobjectdef(ppointerdef(p^.resulttype)^.definition)^.vmt_offset;
  1308. {$ifndef noAllocEdi}
  1309. getexplicitregister32(R_EDI);
  1310. {$endif noAllocEdi}
  1311. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  1312. emit_sym(A_PUSH,S_L,
  1313. newasmsymbol(pobjectdef(ppointerdef(p^.resulttype)^.definition)^.vmt_mangledname));
  1314. emit_reg(A_PUSH,S_L,R_EDI);
  1315. {$ifndef noAllocEdi}
  1316. ungetregister32(R_EDI);
  1317. {$endif noAllocEdi}
  1318. emitcall('FPC_CHECK_OBJECT_EXT');
  1319. emitlab(nillabel);
  1320. end;
  1321. {$endif TESTOBJEXT2}
  1322. end;
  1323. {*****************************************************************************
  1324. SecondIs
  1325. *****************************************************************************}
  1326. procedure secondis(var p : ptree);
  1327. var
  1328. pushed : tpushed;
  1329. begin
  1330. { save all used registers }
  1331. pushusedregisters(pushed,$ff);
  1332. secondpass(p^.left);
  1333. clear_location(p^.location);
  1334. p^.location.loc:=LOC_FLAGS;
  1335. p^.location.resflags:=F_NE;
  1336. { push instance to check: }
  1337. case p^.left^.location.loc of
  1338. LOC_REGISTER,LOC_CREGISTER:
  1339. begin
  1340. emit_reg(A_PUSH,
  1341. S_L,p^.left^.location.register);
  1342. ungetregister32(p^.left^.location.register);
  1343. end;
  1344. LOC_MEM,LOC_REFERENCE:
  1345. begin
  1346. emit_ref(A_PUSH,
  1347. S_L,newreference(p^.left^.location.reference));
  1348. del_reference(p^.left^.location.reference);
  1349. end;
  1350. else internalerror(100);
  1351. end;
  1352. { generate type checking }
  1353. secondpass(p^.right);
  1354. case p^.right^.location.loc of
  1355. LOC_REGISTER,LOC_CREGISTER:
  1356. begin
  1357. emit_reg(A_PUSH,
  1358. S_L,p^.right^.location.register);
  1359. ungetregister32(p^.right^.location.register);
  1360. end;
  1361. LOC_MEM,LOC_REFERENCE:
  1362. begin
  1363. emit_ref(A_PUSH,
  1364. S_L,newreference(p^.right^.location.reference));
  1365. del_reference(p^.right^.location.reference);
  1366. end;
  1367. else internalerror(100);
  1368. end;
  1369. emitcall('FPC_DO_IS');
  1370. emit_reg_reg(A_OR,S_B,R_AL,R_AL);
  1371. popusedregisters(pushed);
  1372. maybe_loadesi;
  1373. end;
  1374. {*****************************************************************************
  1375. SecondAs
  1376. *****************************************************************************}
  1377. procedure secondas(var p : ptree);
  1378. var
  1379. pushed : tpushed;
  1380. begin
  1381. secondpass(p^.left);
  1382. { save all used registers }
  1383. pushusedregisters(pushed,$ff);
  1384. { push instance to check: }
  1385. case p^.left^.location.loc of
  1386. LOC_REGISTER,LOC_CREGISTER:
  1387. emit_reg(A_PUSH,
  1388. S_L,p^.left^.location.register);
  1389. LOC_MEM,LOC_REFERENCE:
  1390. emit_ref(A_PUSH,
  1391. S_L,newreference(p^.left^.location.reference));
  1392. else internalerror(100);
  1393. end;
  1394. { we doesn't modifiy the left side, we check only the type }
  1395. set_location(p^.location,p^.left^.location);
  1396. { generate type checking }
  1397. secondpass(p^.right);
  1398. case p^.right^.location.loc of
  1399. LOC_REGISTER,LOC_CREGISTER:
  1400. begin
  1401. emit_reg(A_PUSH,
  1402. S_L,p^.right^.location.register);
  1403. ungetregister32(p^.right^.location.register);
  1404. end;
  1405. LOC_MEM,LOC_REFERENCE:
  1406. begin
  1407. emit_ref(A_PUSH,
  1408. S_L,newreference(p^.right^.location.reference));
  1409. del_reference(p^.right^.location.reference);
  1410. end;
  1411. else internalerror(100);
  1412. end;
  1413. emitcall('FPC_DO_AS');
  1414. { restore register, this restores automatically the }
  1415. { result }
  1416. popusedregisters(pushed);
  1417. maybe_loadesi;
  1418. end;
  1419. end.
  1420. {
  1421. $Log$
  1422. Revision 1.105 2000-04-10 12:23:19 jonas
  1423. * modified copyshortstring so it takes an extra paramter which allows it
  1424. to delete the sref itself (so the reg deallocations are put in the
  1425. right place for the optimizer)
  1426. Revision 1.104 2000/03/31 22:56:45 pierre
  1427. * fix the handling of value parameters in cdecl function
  1428. Revision 1.103 2000/02/19 10:12:47 florian
  1429. * fixed one more internalerror 10
  1430. Revision 1.102 2000/02/09 13:22:46 peter
  1431. * log truncated
  1432. Revision 1.101 2000/01/13 16:52:48 jonas
  1433. * moved deallocation of registers used in reference that points to string after
  1434. copyshortstring (this routine doesn't require extra regs)
  1435. Revision 1.100 2000/01/09 12:35:00 jonas
  1436. * changed edi allocation to use getexplicitregister32/ungetregister
  1437. (adapted tgeni386 a bit for this) and enabled it by default
  1438. * fixed very big and stupid bug of mine in cg386mat that broke the
  1439. include() code (and make cycle :( ) if you compiled without
  1440. -dnewoptimizations
  1441. Revision 1.99 2000/01/09 01:44:19 jonas
  1442. + (de)allocation info for EDI to fix reported bug on mailinglist.
  1443. Also some (de)allocation info for ESI added. Between -dallocEDI
  1444. because at this time of the night bugs could easily slip in ;)
  1445. Revision 1.98 2000/01/07 01:14:20 peter
  1446. * updated copyright to 2000
  1447. Revision 1.97 1999/12/22 01:01:46 peter
  1448. - removed freelabel()
  1449. * added undefined label detection in internal assembler, this prevents
  1450. a lot of ld crashes and wrong .o files
  1451. * .o files aren't written anymore if errors have occured
  1452. * inlining of assembler labels is now correct
  1453. Revision 1.96 1999/12/21 11:49:51 pierre
  1454. * array of char to short string bug fixed
  1455. Revision 1.95 1999/12/01 12:42:31 peter
  1456. * fixed bug 698
  1457. * removed some notes about unused vars
  1458. Revision 1.94 1999/11/29 22:15:25 pierre
  1459. * fix for internalerror(12) on ord(booleanarray[1])
  1460. Revision 1.93 1999/11/06 14:34:17 peter
  1461. * truncated log to 20 revs
  1462. Revision 1.92 1999/10/25 10:32:43 peter
  1463. * ansistring 2 chararray support
  1464. * optimized ansitring 2 pchar
  1465. Revision 1.91 1999/10/22 14:36:04 peter
  1466. * fixed esi reload with as
  1467. Revision 1.90 1999/10/06 08:32:00 peter
  1468. * fixed empty const ansistring 2 pchar
  1469. Revision 1.89 1999/09/26 21:30:15 peter
  1470. + constant pointer support which can happend with typecasting like
  1471. const p=pointer(1)
  1472. * better procvar parsing in typed consts
  1473. Revision 1.88 1999/09/26 13:26:04 florian
  1474. * exception patch of Romio nevertheless the excpetion handling
  1475. needs some corections regarding register saving
  1476. * gettempansistring is again a procedure
  1477. Revision 1.87 1999/09/23 21:20:37 peter
  1478. * fixed temp allocation for short->ansi
  1479. Revision 1.86 1999/09/01 09:42:13 peter
  1480. * update for new push_lea_loc
  1481. Revision 1.85 1999/08/19 13:08:46 pierre
  1482. * emit_??? used
  1483. Revision 1.84 1999/08/05 14:58:03 florian
  1484. * some fixes for the floating point registers
  1485. * more things for the new code generator
  1486. Revision 1.83 1999/08/04 13:45:19 florian
  1487. + floating point register variables !!
  1488. * pairegalloc is now generated for register variables
  1489. Revision 1.82 1999/08/04 00:22:43 florian
  1490. * renamed i386asm and i386base to cpuasm and cpubase
  1491. }